繁体   English   中英

如何避免在Java中忙于旋转

[英]How to avoid busy spinning in Java

我有一个多线程应用程序,其中一个线程将消息发送到另一个线程。 等待线程轮询消息并做出反应(处理锁定)。 像这样:

等待线程代码:

while(true)
{
  if(helloArrived())
    System.out.println("Got hello");
  if(byeArrived())
    System.out.println("Got bye");
  if(stopArrived())
    break;
}

我想避免这种cpu占用技术,而是使用别的东西。 有任何想法吗?

编辑:实际代码如下:

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

避免这种情况的正确方法是使用java.lang.Object实现的wait / notify机制,或者Java类库提供的更高级别的并发机制之一:

(选择与您的具体用例最匹配的机制......)


使用Thread.sleep不是一个好的解决方案。 虽然您减少了CPU负载(与轮询循环相比),但另一方面是您降低了响应速度。


我现在正在使用BlockingQueue。 但也许我做错了。 我刚刚添加了上面的实际代码。 你看到我的问题了吗?

是啊。 您正在以避免阻止的方式使用队列。 这是错误的做法。 您应该使用take() (它将阻塞直到条目可用)而不是poll() ,并删除测试队列大小的代码。

您的“killMeMailbox”内容似乎旨在让您停止等待邮件。 您应该能够使用Thread.interrupt实现它。 (中断将取消阻止take()调用...)

你正在忙着等待 你永远不应该这样做,因为它会浪费CPU周期。 等待某个事件的线程或进程应处于阻塞状态 以下是实现此目的的可能方法:

如果您可以根据任务执行器重新表述您的问题,那么请考虑使用SingleThreadExecutor 如果您需要更具异国情调的东西 - 并发队列甚至是wait()/ notify()

您是否尝试过一些Thread.sleep以避免不断执行while循环? 它会为你的其他线程释放CPU并避免生猪

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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