我有多个消费者线程使用 await()
等待大小为 1 的 CountDownLatch
。我有一个生产者线程,它在成功完成时调用 countDown()
。
这在没有错误的情况下效果很好。
但是,如果生产者检测到错误,我希望它能够向消费者线程发出错误信号。理想情况下,我可以让生产者调用类似 abortCountDown()
的东西,并让所有消费者收到 InterruptedException 或其他一些异常。我不想调用 countDown()
,因为这需要我所有的消费者线程在调用 await()
之后再进行一次额外的手动检查是否成功。我宁愿他们只收到一个他们已经知道如何处理的异常。
我知道 CountDownLatch
中没有中止功能。是否有另一个同步原语,我可以轻松适应以有效创建支持中止倒计时的 CountDownLatch
?
最佳答案
JB Nizet 给出了很好的答案。我拿了他的并稍微擦亮了它。结果是 CountDownLatch 的一个子类称为 AbortableCountDownLatch,它向该类添加了一个“abort()”方法,这将导致所有等待闩锁的线程接收到 AbortException(InterruptedException 的一个子类)。
此外,与 JB 的类不同,AbortableCountDownLatch 将在中止时立即中止所有阻塞线程,而不是等待倒计时达到零(对于使用计数>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);
}
}
}
关于java - 我如何 "cancel"一个 CountDownLatch?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10453876/