我有等待一個布爾值來改變這樣一個主題:等到布爾值,改變它的狀態
while(!value)
{
Thread.sleep(1000)
}
// Do some work after change of the value
這不是我要做到這一點首選方式,大規模的CPU消耗的原因。
有什麼辦法阻止線程,直到布爾值改變它的狀態?
我有等待一個布爾值來改變這樣一個主題:等到布爾值,改變它的狀態
while(!value)
{
Thread.sleep(1000)
}
// Do some work after change of the value
這不是我要做到這一點首選方式,大規模的CPU消耗的原因。
有什麼辦法阻止線程,直到布爾值改變它的狀態?
這並不是我的首選方式,因此會導致大量CPU消耗。
如果這實際上是您的工作代碼,那麼就保持它那樣。每秒檢查布爾值會導致無可測量的CPU負載。沒有任何。
真正的問題是,檢查值的線程可能看不到由於高速緩存而發生的任意長時間的更改。爲確保該值線程之間總是同步的,你需要把變量定義volatile關鍵字,即
private volatile boolean value;
注意投入塊的訪問,比如使用基於通知的解決方案時,如在其他答案中描述,將具有相同的效果。
怎麼樣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();
}
}
'bool'是一個可變字段,您不能同步它。 – axtavt
嗯......這實際上是一個尖銳的點@axtavt。 –
現在,您正在同步非最終字段。在'setChange'中,你將首先修改它,然後通知新的'false'實例。結果:在較早的'true'實例上等待的線程永遠不會收到通知。又一個很好的例子說明爲什麼要避免這整個機制。 –
你需要避免了忙等待的機制。老wait/notify
機制是充滿陷阱所以更喜歡從java.util.concurrent
庫的東西,例如CountDownLatch
:
public final CountDownLatch latch = new CountDownLatch(1);
public void run() {
latch.await();
...
}
,而在另一端調用
yourRunnableObj.latch.countDown();
然而,啓動一個線程什麼也不做,但等到需要時仍然不是最好的方法。您也可以使用ExecutorService
作爲一項任務提交給您,在滿足條件時必須完成的工作。
這幫助我測試JUnit中的Quartz庫。 Quartz在有自己的線程池的黑盒中運行它的工作。我可以給JUnit發信號,等待石英作業完成,使用java文檔中指定的確切模式。 –
我可以推薦'Java.util.concurrent.BlockingQueue'及其各種實現嗎? 'take()'和'offer()'方法是同步的好起點。 – Groostav
我更喜歡在這種情況下使用互斥體機制,但是如果您真的想使用布爾值,那麼您應該聲明它爲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
}
};
這不會嚼碎CPU嗎? –
好吧,也許這一個應該解決您的問題。請注意,每次您進行更改時,都會調用釋放等待的change()方法。
Integer any = new Integer(0);
public synchronized boolean waitTillChange() {
any.wait();
return true;
}
public synchronized void change() {
any.notify();
}
整型是不可變的,你不能改變它的值 – Andrejs
用於提示「volatile」的+1 ... – TheLostMind