簡體   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