Java - изящно выходить из потоков - PullRequest
2 голосов
/ 29 июня 2011

У меня есть куча потоков, которые выполняют вычисления.Они «синхронизируются» с помощью 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();
    }
}

Ответы [ 2 ]

3 голосов
/ 29 июня 2011

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)

0 голосов
/ 29 июня 2011

Из его звуков вы, вероятно, захотите 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(), барьер преодолевается и выдается исключение.

...