簡體   English   中英

Java ArrayBlockingQueue 阻塞直到隊列中有東西

[英]Java ArrayBlockingQueue blocking until the queue has something in it

我有許多不同的套接字連接到我的代碼,每個套接字都在獨立線程上偵聽。 在將對象傳遞到這些套接字中的任何一個之前,時間可能會過去。 所以我有一個基本上永遠運行的 while(running) 循環。

然后為了同步所有不同的線程,我有一個 ArrayBlockingQueue。 每當套接字/線程組合接收到一個對象時,我就會將該對象添加到 ArrayBlockingQueue(因為它會自動為我同步)。 然后在 while(running) 代碼中,我刪除對象並處理它。

問題是處理器在那個 while(running) 循環中變得瘋狂......理想情況下,我想阻止開始處理所有對象,直到 ArrayBlockingQueue 實際上有一些東西要處理,希望處理器不會繼續運行。

你知道這是否可能?

這是我當前的代碼,它導致處理器旋轉並浪費周期......

@Override
    public void run()
    {
        while(running)
        {
            while(messageQueue.size() > 0)
            {
                Object o = messageQueue.remove();
            }
        }
    }

這是我想要的...

@Override
    public void run()
    {
        while(running)
        {
            messageQueue.BlockUntilSomethingInHere();

            while(messageQueue.size() > 0)
            {
                Object o = messageQueue.remove();
            }
        }
    }

請注意,在執行messageQueue.remove()之前檢查messageQueue.size() > 0被稱為check-then-act反模式。 如果您有多個線程移除元素,則有可能條件在檢查和后續操作之間發生變化,從而導致異常。

只需使用take()而不是remove()

while(running) try {
    Object o = messageQueue.take();
    // ...
} catch(InterruptedException ex) {
    // (running) will be checked before the next loop iteration
}

take()將等待元素變為可用。 要在隊列為空時結束此循環,您必須將running設置為false並中斷線程。 如果無法中斷,您可以使用定時等待:

while(running) try {
    Object o = messageQueue.poll​(1, TimeUnit.SECOND);
    if(o != null) {
        // ...
    }
}
catch(InterruptedException ex) {
  // (running) will be checked before the next loop iteration
}

然后,可能需要一秒鍾,直到等待空隊列的線程對running設置為false做出反應(請注意將running聲明為volatile )。 可以更改超時時間,以權衡響應能力和 CPU 消耗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM