2013-09-26 29 views
31

我有等待一個布爾值來改變這樣一個主題:等到布爾值,改變它的狀態

while(!value) 
{ 
    Thread.sleep(1000) 
} 
// Do some work after change of the value 

這不是我要做到這一點首選方式,大規模的CPU消耗的原因。

有什麼辦法阻止線程,直到布爾值改變它的狀態?

回答

58

這並不是我的首選方式,因此會導致大量CPU消耗。

如果這實際上是您的工作代碼,那麼就保持它那樣。每秒檢查布爾值會導致無可測量的CPU負載。沒有任何。

真正的問題是,檢查值的線程可能看不到由於高速緩存而發生的任意長時間的更改。爲確保該值線程之間總是同步的,你需要把變量定義volatile關鍵字,即

private volatile boolean value; 

注意投入​​塊的訪問,比如使用基於通知的解決方案時,如在其他答案中描述,將具有相同的效果。

+4

用於提示「volatile」的+1 ... – TheLostMind

7

怎麼樣wait-notify

private Boolean bool = true; 
private final Object lock = new Object(); 

private Boolean getChange(){ 
    synchronized(lock){ 
    while (bool) { 
     bool.wait(); 
    } 
    } 
    return bool; 
} 
public void setChange(){ 
    synchronized(lock){ 
     bool = false; 
     bool.notify(); 
    } 
} 
+7

'bool'是一個可變字段,您不能同步它。 – axtavt

+0

嗯......這實際上是一個尖銳的點@axtavt。 –

+0

現在,您正在同步非最終字段。在'setChange'中,你將首先修改它,然後通知新的'false'實例。結果:在較早的'true'實例上等待的線程永遠不會收到通知。又一個很好的例子說明爲什麼要避免這整個機制。 –

34

你需要避免了忙等待的機制。老wait/notify機制是充滿陷阱所以更喜歡從java.util.concurrent庫的東西,例如CountDownLatch

public final CountDownLatch latch = new CountDownLatch(1); 

public void run() { 
    latch.await(); 
    ... 
} 

,而在另一端調用

yourRunnableObj.latch.countDown(); 

然而,啓動一個線程什麼也不做,但等到需要時仍然不是最好的方法。您也可以使用ExecutorService作爲一項任務提交給您,在滿足條件時必須完成的工作。

+0

這幫助我測試JUnit中的Quartz庫。 Quartz在有自己的線程池的黑盒中運行它的工作。我可以給JUnit發信號,等待石英作業完成,使用java文檔中指定的確切模式。 –

+0

我可以推薦'Java.util.concurrent.BlockingQueue'及其各種實現嗎? 'take()'和'offer()'方法是同步的好起點。 – Groostav

1

我更喜歡在這種情況下使用互斥體機制,但是如果您真的想使用布爾值,那麼您應該聲明它爲volatile(以提供跨線程的可見性更改),並使用該布爾值運行body-less循環作爲一個條件:

//.....some class 

volatile boolean someBoolean; 

Thread someThread = new Thread() { 

    @Override 
    public void run() { 
     //some actions 
     while (!someBoolean); //wait for condition 
     //some actions 
    } 

}; 
+15

這不會嚼碎CPU嗎? –

2

好吧,也許這一個應該解決您的問題。請注意,每次您進行更改時,都會調用釋放等待的change()方法。

Integer any = new Integer(0); 

public synchronized boolean waitTillChange() { 
    any.wait(); 
    return true; 
} 

public synchronized void change() { 
    any.notify(); 
} 
+2

整型是不可變的,你不能改變它的值 – Andrejs