[英]Java: Wait a boolean to become true
我實現了一個任務,當前線程將等到之前的工作完成。
碼:
while (!taskContext.isPreviousWorkDone()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
LOGGER.error("Wait failed", e);
}
}
doSomething();
另一個線程將isPreviousWorkDone
設置為true,然后我們可以運行doSomething()
。 但是我認為我的代碼很糟糕:
100ms
檢查一次,這可能會花費一些CPU資源。 isPreviousWorkDone
從未變為真怎么辦?) 那么,如何正確執行這樣的等待呢?
請改用CountDownLatch 。 一個java.util.concurrent.CountDownLatch允許一個或多個線程等待某些操作完成。
CountDownLatch用給定的計數初始化。 需要等待某種條件/操作(計數達到零)的線程,調用await()方法之一。 通過調用countdown()方法,計數從完成某些操作的線程中減少。 然后,所有等待線程繼續執行。
例
// create latch with count of one (1)
CountDownLatch latch = new CountDownLatch(1);
// create instances of classes that implement Runnable
Waiter waiter = new Waiter(latch);
Worker worker = new Worker(latch);
// start threads
new Thread(waiter).start();
new Thread(worker).start();
定義Waiter Runnable(等待某些操作完成)
public class Waiter implements Runnable{
CountDownLatch latch = null;
public Waiter(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
try {
// wait for the latch to be released
latch.await();
} catch (InterruptedException e) {
// set interupt flag
Thread.currentThread().interrupt();
// log interrupt
System.out.println("Interrupted");
}
System.out.println("Unblocked");
doSomething();
}
}
定義Worker Runnable(執行一些操作)
public class Worker implements Runnable {
CountDownLatch latch = null;
public Worker(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
// do some job
// when ready release latch
latch.countDown();
System.out.println("Latch Released");
}
}
避免
使用舊的等待通知 Java API。 原因是虛假的喚醒 。 那是您的線程在沒有得到實際通知的情況下被喚醒,因此您必須檢查條件是否得到滿足,否則將繼續等待。
線程也可以喚醒,而不會被通知,中斷或超時,即所謂的虛假喚醒。 盡管在實踐中這種情況很少發生,但是應用程序必須通過測試應該導致線程喚醒的條件來防范它,並在條件不滿足時繼續等待。 換句話說,等待應該總是像這樣循環執行:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(有關此主題的更多信息,請參閱Doug Lea的“ Java並行編程(第二版)”(Addison-Wesley,2000年)中的3.2.3節,或Joshua Bloch的“有效的Java編程語言指南”(Addison-衛斯理,2001)。
您想要實現的是顯示器的工作。 使用充當監視器的對象,您可以在需要時使線程等待/喚醒。
synchronized(lock)
{
while(!taskContext.isPreviousWorkDone())
{
try
{
// Object lock has to be accessible both by waiting thread and any
// other thread that marks the previous work as done
lock.wait();
}
}
}
現在,無論您在哪里更新任務上下文,都必須喚醒等待線程
// Method where you update taskContext
public synchronized void setWorkAsDone() throws Exception
{
// ...
_isPreviousWorkDone = true;
notifyAll();
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.