Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid busy spinning in Java

I have a multi-threaded application where a thread sends a message to another thread. The waiting thread polls for the message and reacts (locks are handled). Like this:

Waiting thread 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());
            }
        }
    }
like image 352
Josh Avatar asked Oct 24 '14 07:10

Josh


People also ask

How can the busy waiting be avoided?

To avoid busy waiting, a semaphore may use an associated queue of processes that are waiting on the semaphore, allowing the semaphore to block the process and then wake it when the semaphore is incremented.

What is busy spinning in Java?

Busy Spinning is a wait strategy in which one thread waits for some condition to happen which is to be set by some other thread. Here the waiting thread loops continuously without releasing the CPU cycles. This leads to bad performance as the CPU cycles are wasted by a waiting thread.

What is busy waiting in multi threading?

In computer science and software engineering, busy-waiting, busy-looping or spinning is a technique in which a process repeatedly checks to see if a condition is true, such as whether keyboard input or a lock is available.

Is thread sleep busy waiting?

It depends on the operating system and the exact number of milliseconds you are sleeping. If the sleep is sufficiently long that the operating system can switch to another task, populate its caches, and usefully run that task until your task is ready-to-run again, then it's not busy waiting. If not, then it is.


2 Answers

The correct way to avoid this is to use the wait/notify mechanism implemented by java.lang.Object, or one of the higher level concurrency mechanisms provided by the Java class libraries:

  • semaphores,
  • latches / cyclic barriers,
  • blocking queues; e.g. the classes that implemented the BlockingQueue interface.

(Pick the mechanism that is the best match for what your specific use-case ...)


Using Thread.sleep is not a good solution. While you reduce CPU load (compared with a polling loop), the flip-side is that you reduce responsiveness.


I'm using a BlockingQueue now. But maybe I'm doing it incorrectly. I just added the actually code above. Do you see my problem?

Yea. You are using the queue in a way that is designed to avoid blocking. That's the wrong approach. You should use take() (which will block until an entry becomes available) instead of poll(), and get rid of the code that tests the queue size.

Your "killMeMailbox" stuff seems to be designed to allow you to stop waiting for mail. You should be able to implement that using Thread.interrupt. (An interrupt will unblock a take() call ...)

like image 60
Stephen C Avatar answered Sep 22 '22 04:09

Stephen C


You're doing busy waiting. You should never do that because it wastes CPU cycles. A thread or process waiting for some event should be in blocked state. Here are possible ways to achieve this:

  • Use Semaphores
  • Use synchronized methods with wait/notify
  • For specifically exchanging messages between threads, using BlockingQueues may be the best option
like image 22
ChrisJ Avatar answered Sep 25 '22 04:09

ChrisJ