简体   繁体   中英

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());
            }
        }
    }

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:

(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 ...)

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:

If you can reformulate your problem in terms of task-executor then consider using a SingleThreadExecutor . If you need something more exotic - either a concurrent queue or even wait()/notify() .

Have you tried to put some Thread.sleep to avoid executing the while loop constantly? It will liberate CPU for your other threads and avoid hogs

http://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM