I have multiple consumer threads waiting on a CountDownLatch
of size 1 using await()
. I have a single producer thread that calls countDown()
when it successfully finishes.
This works great when there are no errors.
However, if the producer detects an error, I would like for it to be able to signal the error to the consumer threads. Ideally I could have the producer call something like abortCountDown()
and have all of the consumers receive an InterruptedException or some other exception. I don't want to call countDown()
, because this requires all of my consumer threads to then do an additional manual check for success after their call to await()
. I'd rather they just receive an exception, which they already know how to handle.
I know that an abort facility is not available in CountDownLatch
. Is there another synchronization primitive that I can easily adapt to effectively create a CountDownLatch
that supports aborting the countdown?
Every time when CountDownLatch. countDown() is called, the value of count will decrease by 1 until the value becomes 0. One thing to be noted is that the value of count cannot be reset. i.e, when count becomes 0, the CountDownLatch will not work anymore, the call to await() method will return immediately.
As stated in the definitions, CyclicBarrier allows a number of threads to wait on each other, whereas CountDownLatch allows one or more threads to wait for a number of tasks to complete. In short, CyclicBarrier maintains a count of threads whereas CountDownLatch maintains a count of tasks.
await() Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted. boolean. await(long timeout, TimeUnit unit) Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses.
JB Nizet had a great answer. I took his and polished it a little bit. The result is a subclass of CountDownLatch called AbortableCountDownLatch, which adds an "abort()" method to the class that will cause all threads waiting on the latch to receive an AbortException (a subclass of InterruptedException).
Also, unlike JB's class, the AbortableCountDownLatch will abort all blocking threads immediately on an abort, rather than waiting for the countdown to reach zero (for situations where you use a count>1).
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class AbortableCountDownLatch extends CountDownLatch {
protected boolean aborted = false;
public AbortableCountDownLatch(int count) {
super(count);
}
/**
* Unblocks all threads waiting on this latch and cause them to receive an
* AbortedException. If the latch has already counted all the way down,
* this method does nothing.
*/
public void abort() {
if( getCount()==0 )
return;
this.aborted = true;
while(getCount()>0)
countDown();
}
@Override
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
final boolean rtrn = super.await(timeout,unit);
if (aborted)
throw new AbortedException();
return rtrn;
}
@Override
public void await() throws InterruptedException {
super.await();
if (aborted)
throw new AbortedException();
}
public static class AbortedException extends InterruptedException {
public AbortedException() {
}
public AbortedException(String detailMessage) {
super(detailMessage);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With