2013-12-18 4 views
1

Я пишу код, где мне нужно убедиться, что нить не выполняется в пуле потоков до того, как я зафиксирую результаты (чтобы не потерять данные, которые я должен был бы положить в фиксацию). Для этого я использую:Как я могу сказать, что потоки в ThreadPoolExecutor выполнены?

while (_executor.getActiveCount() > 0) 
{ 
    try 
    { 
    Thread.sleep(10); // milliseconds 
    } 
    catch (InterruptedException e) 
    { 
    // OK do nothing 
    } 
} 

Но коллега отметил в обзоре, что документ для getActiveCount гласит:

  • Возвращает приблизительное количество потоков, которые активно
  • выполнения задания.

Итак, есть риск, который я бы выйти из цикла в то время, пока все еще активных потоков в пуле? Если да, то каков был бы правильный способ дождаться завершения всех моих рабочих потоков?

Редактировать: Чтобы добавить еще какой-либо контекст: это онлайн-система, в которой задача, содержащая службу-исполнитель, остается неопределенной. Работа приходит через систему обмена сообщениями, помещается в поток в исполнителе, который не нуждается в синхронизации, и работы выходят в другую очередь для системы обмена сообщениями. Я не хочу убивать исполнителя, чтобы дождаться завершения задач.

+0

Не могли бы вы подождать выполнения задач, вместо того, чтобы ждать исполнителя быть без работы? http://stackoverflow.com/questions/12896755/executorservice-with-invokeall-and-future-in-java – zapl

ответ

4

Вы можете рассмотреть с помощью CompletionService (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html).

A CompletionService обертывает ExecutorService и возвращает Future при выполнении задач. Сохраняя список из этих Future, вы можете увидеть, завершились ли задания, которые вы ожидаете. У него также есть дополнительное преимущество, что вы можете использовать других тех же ExecutorService, поскольку у вас есть какие-то средства бухгалтерского учета,

0

Чтобы уведомить поток, который он должен очистить и завершить, используйте метод прерывания. t.interrupt();

и хорошо печатать или записывать ваши ошибки из блока catch.

1

_executor.awaitTermination(); должен выполнить эту работу. Теперь на самом деле он не будет ждать завершения потоков, но скорее будет ждать завершения всех доступных задач.

Вы также могли бы обеспечить keepAliveTime конструктору пула потоков немедленно прекратить праздные темы:

ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */, 
     TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); 
0

Когда задачи передаются исполнителю, они возвращают Фьючерсы, которые указывают, когда они завершатся. Это предпочтительный механизм для использования.

Вы можете использовать JDK ExecutorService shutdown/awaitTermination.

+0

'Возвращение исполнителей. Чтобы получить 'Future', вам нужно использовать' CompletionService'. – bstempi

+0

@bstempi 'ExecutorService' возвращает '' Будущее и пустоту '. 'ExecutorService.submit' возвращает фьючерсы как для Runnables, так и для Callables. –

+0

Интерфейс JDK 'ExecutorService' - и все реализующие классы - абсолютно возвращает Futures. – user2684301

0

Использование: необходимо очистить потоковые локаторы в потоках пулов после их завершения, и эта очистка может занять много времени (например, закрыть соединение). Только после этого основной поток может продолжаться.

Рабочая нить может регистрироваться в какой-либо коллекции.Для этого переопределения start() и run() и передать пользовательские нити завода в ThreadPoolExecutor:

class MyThreadFactory implements ThreadFactory { 

    @Override 
    public Thread newThread(final Runnable r) { 
     return new MyThread(r); 
    } 
... 

class Some { 
    void waitAllThreads() { 
     Thread worker; 
     while ((worker = workerThreads.poll()) != null) { 
      worker.join(); 
     } 
    } 
    ... 

class MyThread extends Thread { 

    @Override 
    public synchronized void start() { 
     if (getState() == State.NEW) { 
      some.workerThreads.offer(this); 
     } 
     super.start(); 
    } 

    @Override 
    public void run() { 
     try { 
      super.run(); 
     } finally { 
      some.workerThreads.remove(this); 
     } 
    } 

    ... 
Смежные вопросы