【问题标题】:Java - gracefully quit threadsJava - 优雅地退出线程
【发布时间】:2011-06-28 21:01:40
【问题描述】:

我有一堆执行计算的线程。它们使用CyclicBarrier“同步”。当任何线程的run()方法完成时,我希望所有其他线程在下次调用屏障上的await()时也退出。

到目前为止,我尝试过的所有操作要么在await() 调用时挂起,要么导致障碍被破坏。有什么建议吗?

编辑:这是(基本)代码:

public MyClass implements Runnable {
    public void run() {
        while (true) {
            if (someCondition) {
                // quit other threads when they call await()
                return;
            }
            barrier.await();
    }
}

【问题讨论】:

  • 显示代码,这个很难回答。
  • @ryyst,我认为 CyclicBarrier 不会做你想做的事。
  • @Peter Lawrey:那我还应该选择什么。它实际上非常适合我的问题(除了戒烟部分)。
  • 您是否充分同步,以使影响someCondition 的变量的更改对其他线程可见?
  • 显示更多代码,具体来说,什么是“someCondition”并显示其中所有内容的对象声明

标签: java concurrency cyclicbarrier


【解决方案1】:

reset() 将唤醒所有等待的线程并抛出异常

然后你就可以使用 await 了

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)检查的方法

【讨论】:

  • 如果障碍因其他原因而破裂怎么办?您的解决方案实际上就像我目前已经实现的一样,但我对此并不满意。
  • @ryyst,你对什么不满意?在不知道这一点的情况下,很难提出替代方案。
  • 在 catch 中做一个额外的检查,但是如果屏障被破坏,则需要一些额外的同步才能继续,并且仅当您使用超时和中断(或引发异常的屏障操作)时才会发生破坏)
【解决方案2】:

听上去你可能想要CountDownLatch。假设您知道线程/参与者的数量,您只需为这么多创建一个,然后当您的线程完成倒计时并等待闩锁:

final int workers = …
final CountDownLatch latch = new CountDownLatch(workers);

void doSomething() throws InterruptedException {
  …
  latch.countDown();
  latch.await(); // blocks, throws InterruptedException
}

相比CyclicBarrier,CountDownLatch 不可重复使用,只能使用一次。然而,它确实将等待和释放问题分开,因此您可以拥有另一个允许线程通过的线程。

综上所述,如果您确实需要CyclicBarrier,对上述代码稍作改动应该可以工作:

final int workers = …
final CyclicBarrier barrier = new CyclicBarrier(workers);

void doSomething() throws InterruptedException, BrokenBarrierException {
  …
  latch.await(); // blocks, throws InterruptedException, BrokenBarrierException
}

但是,如果任何线程被中断或barrier.reset() 被调用,则屏障被打破并引发异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2011-10-20
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多