How to avoid being busy in Java
I have a multi-threaded application where a thread is sending a message to another thread. The pending thread polls for a message and responds (locks are being processed). Like this:
Wait sequence code:
while(true)
{
if(helloArrived())
System.out.println("Got hello");
if(byeArrived())
System.out.println("Got bye");
if(stopArrived())
break;
}
I want to avoid this cpu hogging technique and use something else instead. Any ideas?
Edit: the actual code is below:
BlockingQueue<Mail> killMeMailbox = new LinkedBlockingQueue<Mail>();
BlockingQueue<Mail> messageMailbox = new LinkedBlockingQueue<Mail>();
public void run()
{
while(true)
{
if(killMeMailbox.size() > 0)
{
break;
}
if(messageMailbox.size() > 0)
{
System.out.println(messageMailbox.poll());
}
}
}
public void receiveMail(Mail mail)
{
//kill
if(mail.from == -1)
{
killMeMailbox.add(0);
}
else
{
//other
try
{
messageMailbox.put(mail);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
source to share
The correct way to avoid this is to use the wait / notify mechanism implemented java.lang.Object
, or one of the higher level concurrency mechanisms provided by the Java class libraries:
- ,
- latches / cyclic barriers ,
- blocking queues; for example classes that have implemented an interface
BlockingQueue
.
(Choose the mechanism that best suits your specific use case)
Using is Thread.sleep
not a good solution. While you reduce the CPU load (versus polling cycle), the flip side is that you reduce responsiveness.
I am now using BlockingQueue. But maybe I am doing it wrong. I just added the code above. Do you see my problem?
Yes. You are using the queue in a way that avoids blocking. This is the wrong approach. You should use take()
(which will block until the entry is available) instead poll()
, and get rid of the code that checks the queue size.
Your "killMeMailbox" stuff seems to be for you to stop waiting for mail. You must implement this with Thread.interrupt
. (Interrupt unblocks call take()
...)
source to share
You make an expectation of expectation . You should never do this because it wastes CPU cycles. A thread or process waiting for an event must be in a blocked state . Possible ways to achieve this are:
- Use Semaphores
- Use synchronized methods with wait / notify
- For accurate messaging between threads, using BlockingQueues may be the best option
source to share
If you can reformulate your problem from the perspective of a task executor, consider using a SingleThreadExecutor . If you need something a little more exotic - a parallel queue or even wait () / notify () .
source to share
Have you tried putting some Thread.sleep to avoid the continuous while loop? It will free up the processor for your other threads and avoid the pigs
http://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html
source to share