54

我有一个线程等待布尔值改变如下:

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

这不是我喜欢的方法,因为会消耗大量 CPU。

有没有办法阻止线程,直到布尔值改变它的状态?

4

6 回答 6

86

这不是我喜欢的方法,因为会消耗大量 CPU。

如果这实际上是您的工作代码,那么就保持这样。每秒检查一次布尔值会导致没有可测量的 CPU 负载。没有任何。

真正的问题是检查值的线程可能看不到由于缓存而在任意长时间内发生的更改。为保证值在线程间始终保持同步,需要在变量定义中放入 volatile 关键字,即

private volatile boolean value;

请注意,将访问放在一个synchronized块中,例如使用其他答案中描述的基于通知的解决方案时,将具有相同的效果。

于 2013-09-26T10:23:23.507 回答
59

您需要一种避免忙等待的机制。旧的wait/notify机制充满了陷阱,所以更喜欢java.util.concurrent图书馆的东西,例如CountDownLatch

public final CountDownLatch latch = new CountDownLatch(1);

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

在另一边打电话

yourRunnableObj.latch.countDown();

但是,启动一个线程只等到需要它时什么都不做,这仍然不是最好的方法。您还可以使用ExecutorService您提交的任务作为满足条件时必须完成的工作。

于 2013-09-26T10:22:46.723 回答
8

怎么样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();
   }
}
于 2013-09-26T10:16:37.130 回答
2

好的,也许这个应该可以解决您的问题。请注意,每次进行更改时,都会调用 change() 方法来释放等待。

Integer any = new Integer(0);

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

public synchronized void change() {
    any.notify();
}
于 2013-09-26T10:30:27.073 回答
0

在这种情况下,我更喜欢使用互斥机制,但如果你真的想使用布尔值,那么你应该将它声明为 volatile(以提供跨线程的更改可见性)并以该布尔值作为条件运行无主体循环:

//.....some class

volatile boolean someBoolean; 

Thread someThread = new Thread() {

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

};
于 2013-09-26T10:25:40.310 回答
0
public Boolean test() throws InterruptedException {
    BlockingQueue<Boolean> booleanHolder = new LinkedBlockingQueue<>();
    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(2);
            booleanHolder.put(true);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    return booleanHolder.poll(4, TimeUnit.SECONDS);
}
于 2020-10-30T07:23:42.033 回答