如何使用 AtomicBoolean 进行阻塞和等待

问题描述 投票:0回答:5

我正在寻找一种暂停线程的方法。

我首先有效地使用布尔标志(称为“暂停”),并用 while 循环包装检查(暂停)。

在 while 循环中,有一个

Thread.wait()
来阻止执行。

我一直在研究 AtomicBoolean,它似乎可以解决问题,除了它不会阻塞。

是否有具有块方法的 AtomicBoolean 替代或扩展版本?

即类似于

AtomicBoolean.getFalse()
AtomoicBoolean.get(false)
的东西?

它们有一个阻塞队列,因此有一个阻塞值。

当前设置是:

while (paused.get()) {
        synchronized (paused) {
            try {

                paused.wait();
            } catch (Exception e) {
            }

            paused.notify();
        }
    }

public void pause() {
    if (paused.compareAndSet(false, true)) {
        synchronized (paused) {
            paused.notify();
        }
    }

}


public void resume() {
    if (paused.compareAndSet(true, false)) {
        synchronized (paused) {
            paused.notify();
        }
    } 
}
java concurrency atomic java.util.concurrent
5个回答
23
投票

使用

CountDownLatch
为 1:

CountDownLatch conditionLatch = new CountDownLatch(1);

在你想要等待某个条件成立的地方:

conditionLatch.await();

在你想要将条件设置为true的地方:

conditionLatch.countDown();

18
投票
    AtomicBoolean lock = new AtomicBoolean(false);
    if(lock.compareAndSet(false, true)){
        try {
            //do something
        } catch(Exception e){
            //error handling
        } finally {
            lock.set(false);
        }
    }

首先,除非您使用原子操作(类似于测试和设置),否则

AtomicBoolean
与常规布尔值一样无用(如果它们是可变的)。这里我使用
compareAndSet
,这样只有在标志关闭时它才会进入临界区。记得一定要最后解锁。

要使用标志暂停线程,不要进行主动等待(线程体中的某个循环询问“我暂停了吗?”),因为这不是一种有效的做法。我会使用等待通知方案。当线程没有更多工作要做时,它会在某个对象上调用

wait
。然后,为了重新启动,其他一些线程在同一对象上调用
notify

如果你想立即暂停(在设置标志时跳过执行),你可以将代码分成尽可能多的步骤,并用测试包装每个步骤,最后在暂停时等待:

public void run(){
    while(true){
        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(paused){
            //wait on some object
        }
    }       
}   

根据您的代码,这些步骤甚至可能是嵌套的,或者包含涉及多个步骤的不可分割的执行单元。


4
投票

我不确定我是否理解了你的问题;你看过班级吗

java.util.concurrent.Semaphore
? 带有
Semaphore
permits=1
应该会给你所需的行为,你可以模仿你的

paused=true;

使用说明

semaphore.tryAcquire();

semaphore.acquire();

如果您想锁定来电者。 您可以使用

释放线程
semaphore.release();

1
投票

您可以使用锁。

在你的帖子中。

while(!Thread.interrupted()) {
  lock.lock();
  try {
      // do something.
  } finally {
      lock.unlock();
  }
}

// to pause
lock.lock();

// to unpause
lock.unlock(); // has to be the same thread which locked.

或者你可以忙着睡觉,这取决于你需要多快的线程唤醒。

while(atomicBoolean.get()) Thread.sleep(100); // or yield();

0
投票

您正在等待特定时间,这可以通过

Thread.sleep()
完成,或者您需要等待 for 某件事,这表明您需要对正在等待准备就绪的对象调用
wait()
.

如果您确实需要手动告诉线程继续工作,请构建一个

while(true)
循环,其中包含
Thread.sleep()
调用并检查布尔值,如果设置正确,该布尔值会导致
break
。但我真的想不出这样做的理由。

© www.soinside.com 2019 - 2024. All rights reserved.