How to Block and wait using AtomicBoolean

北战南征 提交于 2019-12-05 11:46:31

问题


I am looking for a way of pausing a Thread.

I started with affectively using a boolean flag (called 'paused'), and wrapping a check with a while loop (pause).

Within the while loop there’s a Thread.wait() to block the execution.

I’ve been looking at the AtomicBoolean, which seems to do the trick apart from it doesn’t block.

Is there a alternative or extended version of AtomicBoolean that has a block method ?

i.e. something like AtomicBoolean.getFalse() of AtomoicBoolean.get(false)?

They have a Blocking Queue, so a Blocking value.

Current setup is :

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

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

            paused.notify();
        }
    }

with

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

}


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

回答1:


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

First, unless you use an atomic operation (something like test-and-set), AtomicBoolean is as useless as a regular Boolean (If they were mutable). Here I'm using compareAndSet, so that it only enters the critical section if the flag was down. Remember to always unlock in finally.

To pause a thread using a flag, don't go for active wait (some loop in thread body asking "Am I paused?"), as it is not an efficient practice. I'd use a wait-notify scheme. When the thread has no more work to do, it calls wait on some object. Then, to restart, some other thread calls notify on that same object.

If you want to immediately pause (in terms of skip execution when the flag is set), you could divide the code in as much steps as possible, and wrap each one with a test, to finally wait if paused:

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
        }
    }       
}   

Depending of your code, the steps may be even nested, or include undivisible units of execution involving several steps.




回答2:


Use a CountDownLatch of 1:

CountDownLatch conditionLatch = new CountDownLatch(1);

In the place you want to wait for some condition to become true:

conditionLatch.await();

In the place you want to set the condition to true:

conditionLatch.countDown();



回答3:


I'm not sure I did understand your question;anyway did you look at the class java.util.concurrent.Semaphore? A Semaphore with permits=1 should give you the desired behaviour, you can emulate your

paused=true;

instruction with

semaphore.tryAcquire();

or

semaphore.acquire();

if you want to lock the caller. You can release the thread with

semaphore.release();




回答4:


You can use a lock.

In your thread.

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.

Or you could busy sleep depending on how quickly you need a thread to wake up.

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



回答5:


Either you are waiting for a specific time, which can be done with Thread.sleep() or you need to wait for something, which would indicate, that you need to call wait() on the object you are waiting for to be ready.

If you really need to be manually able to tell your thread to continue working, build a while(true) loop containing a Thread.sleep() call and a check for a boolean which leads to a break if properly set. I can't really think of a reason to do that though.



来源:https://stackoverflow.com/questions/8213089/how-to-block-and-wait-using-atomicboolean

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!