How to Block and wait using AtomicBoolean

25,521

Solution 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.

Solution 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();

Solution 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();

Solution 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();
Share:
25,521

Related videos on Youtube

Ben
Author by

Ben

Updated on March 28, 2020

Comments

  • Ben
    Ben about 4 years

    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();
            }
        } 
    }
    
  • Ben
    Ben over 12 years
    i think a lock and only be unlocked from the same thread for if Thread 1 called lock, i don't believe thread 2 can call unlock.
  • Ben
    Ben over 12 years
    i have somthing like this already using a normal boolean and a Sync method like synchronized (this) { while (paused) { try { wait(); } catch (Exception e) { } } this.notify(); } but was hopping for an all inclusive method.
  • Vishy
    Vishy over 12 years
    Yes, that's why I added the comment. ;) IMHO, It seems a bit random if different threads can start/stop this thread.
  • Till Helge
    Till Helge over 12 years
    Well...my point is that you are most likely thinking about your problem the wrong way.
  • Ben
    Ben over 12 years
    the reason for it, come down to pausing execution. I currently have the wait() method. So you have a thread, you want to pause or stop comsuming, a flag is put in place, and at the moment i have a if true, wait on monitor. i was hoping to block on the actual state.
  • Ben
    Ben over 12 years
    Yep, its a web application sending request to a running thread, to get it to pause. i was just looking for a one line way of doing it instead of sync blocks with wait() and notify().
  • Ben
    Ben over 12 years
    i will have a look at this, and test it, but i think the release can only be done by the thread that acquired the permit. Thus Thread 1 can not release a permit that Thread 2 acquired. I think i possible have to stick to Thread.wait()
  • Giovanni
    Giovanni over 12 years
    the javadoc says: There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.
  • Ben
    Ben over 12 years
    thanks, this (boolean with wait-notify method) is pretty much what i did already, but was hoping that there was something already done for me within the concurrency package.
  • FiveO
    FiveO over 10 years
    A static instance of the Semaphore does the job