[英]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.