繁体   English   中英

Java:等待布尔值变为真实

[英]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() 但是我认为我的代码很糟糕:

  1. 我们每100ms检查一次,这可能会花费一些CPU资源。
  2. 很难添加等待超时。 (如果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。 原因是虚假的唤醒 那是您的线程在没有得到实际通知的情况下被唤醒,因此您必须检查条件是否得到满足,否则将继续等待。

来自Javadocs的虚假唤醒

线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。 尽管在实践中这种情况很少发生,但是应用程序必须通过测试应该导致线程唤醒的条件来防范它,并在条件不满足时继续等待。 换句话说,等待应该总是像这样循环执行:

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM