Java-优雅地退出线程
我有一堆执行计算的线程。它们是使用一个“同步”的。当任何线程的Java-优雅地退出线程,java,concurrency,cyclicbarrier,Java,Concurrency,Cyclicbarrier,我有一堆执行计算的线程。它们是使用一个“同步”的。当任何线程的run()方法完成时,我希望所有其他线程在下次调用屏障上的wait()时也退出 到目前为止,我尝试的所有方法要么挂起await()调用,要么导致屏障被打破。有什么建议吗 编辑:以下是(基本)代码: reset()将用抛出的异常唤醒所有等待的线程 然后,您可以使用wait as so private static volatile boolean shouldStop=false; public void run() { tr
run()
方法完成时,我希望所有其他线程在下次调用屏障上的wait()
时也退出
到目前为止,我尝试的所有方法要么挂起await()
调用,要么导致屏障被打破。有什么建议吗
编辑:以下是(基本)代码:
reset()将用抛出的异常唤醒所有等待的线程
然后,您可以使用wait as so
private static volatile boolean shouldStop=false;
public void run() {
try{
while (true) {
if (someCondition) {
// quit other threads when they call await()
return;
}
try{
if(shouldStop)return;
barrier.await();
}catch(BrokenBarrierException e){
//someone stopped
return;
}
}
}finally{
shouldStop =true;
barrier.reset();
}
}
您还可以调用
if(shouldStop)
检查的方法,从它的声音中您可能想要一个。假设您知道线程/参与者的数量,只需为这么多线程创建一个,然后在线程完成后倒计时并等待闩锁:
final int workers = …
final CountDownLatch latch = new CountDownLatch(workers);
void doSomething() throws InterruptedException {
…
latch.countDown();
latch.await(); // blocks, throws InterruptedException
}
与CyclicBarrier
相比,CountDownLatch
不可重用,只能使用一次。然而,它将等待和释放问题分开,因此您可以使用另一个线程来允许线程通过
综上所述,如果您确实需要CyclicBarrier
对上述代码稍加修改即可:
但是,如果任何线程被中断或调用了
barrier.reset()
,那么barrier就会被破坏并引发异常。显示代码,这很难回答。@ryst,我认为CyclicBarrier不会做你想做的。@Peter Lawrey:那么我还应该选择什么呢。它实际上非常适合我的问题(除了退出部分)。您是否进行了充分的同步,以便其他线程可以看到对影响someCondition
的变量所做的更改?显示更多代码,特别是什么是“someCondition”并显示其中所有内容的对象声明。如果障碍因其他原因而打破,该怎么办?你的解决方案实际上就像我现在已经实现了一样,但我不满意。@ryyst,你不满意什么?在不知道这一点的情况下,很难提出替代方案。在捕获中进行额外检查,但如果屏障被破坏,则需要进行一些额外的同步,然后才能继续,并且只有在使用超时和中断(或屏障操作引发异常)时才会发生破坏
final int workers = …
final CountDownLatch latch = new CountDownLatch(workers);
void doSomething() throws InterruptedException {
…
latch.countDown();
latch.await(); // blocks, throws InterruptedException
}
final int workers = …
final CyclicBarrier barrier = new CyclicBarrier(workers);
void doSomething() throws InterruptedException, BrokenBarrierException {
…
latch.await(); // blocks, throws InterruptedException, BrokenBarrierException
}