2016-03-18 2 views
1

У меня есть что-то вроде этого:Как выключение CompletionService после завершения в настоящее время выполняются задачи

ExecutorService executor = Executors.newFixedThreadPool(2); 
CompletionService<Boolean> completionService = new ExecutorCompletionService<>(executor); 
int i = 0; 
while (i < 40) { 
    completionService.submit(getTask()); 
    i++; 
} 
executor.shutdown(); 
System.out.println("SHUTDOWN"); 

После вызова shutdown все представленные задачи выполняются. Если я звоню shutdownNow, то в настоящее время выполняются потоки java.lang.InterruptedException.

Есть ли способ подождать выполненные в данный момент задачи, чтобы выполнить и выполнить другие отправленные задачи?

ответ

3

shutdown() позволяет в настоящее время представленные задачи для завершения, но отвергает новые:

Инициирует процедуру завершения работы, в котором выполняются ранее представленные задачи, но никакие новые задачи не будут приняты.

Если вы хотите, чтобы ждать в вашей main нити для исполнителя, чтобы закрыть, вы можете вызвать executor.awaitTermination(long timeout, TimeUnit unit):

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

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

  • отменяя Фьючерс с cancel(false):

    Попытки отменить выполнение этой задачи. Эта попытка потерпит неудачу, если задача уже завершена, уже отменена или не может быть отменена по какой-либо другой причине. В случае успеха, и эта задача не началась при вызове отмены, эта задача никогда не должна запускаться.

    Возвращает: false, если задача не может быть отменена, как правило, потому что она уже завершена нормально; правда, в противном случае

  • оборачивать ваши Runnable/Callable с пользовательской CancellableRunnable/Callable (в зависимости от ваших getTask() возвращается):

    class CancellableRunnable implements Runnable { 
    
        private final AtomicBoolean shouldRun; 
        private final Runnable delegate; 
    
        public CancellableRunnable(AtomicBoolean shouldRun, Runnable delegate) { 
         this.shouldRun = shouldRun; 
         this.delegate = delegate; 
        } 
    
        @Override 
        public void run() { 
         if (shouldRun.get()) { 
          delegate.run(); 
         } 
        } 
    } 
    

    и использования в вашем примере:

    AtomicBoolean shouldRun = new AtomicBoolean(true); 
    while (i < 40) { 
        completionService.submit(new CancellableRunnable(shouldRun, getTask())); 
        i++; 
    } 
    shouldRun.set(false); 
    executor.shutdown(); 
    
+0

Мне не нужны все поставленные задачи для завершения. Мне нужно подождать только выполненные в настоящее время 2 задачи и не выполнять другие отправленные задачи. – Kirill

+0

@ Кирилл - ок, я понимаю. См. Мое обновление. –

+0

Похоже, что мне нужно. Спасибо, я попробую – Kirill

0

Да, после того, как вы позвонили shutdown(), исполнитель не примет никаких новых заданий. Затем вы вызываете awaitTermination(), чтобы дождаться выполнения заданий.

+1

Не работает. Когда я делаю 'executor.shutdownNow(); executor.awaitTermination (1, TimeUnit.MILLISECONDS); 'тогда все выполняемые задачи будут выполнены. Мне нужно подождать только выполненные в настоящее время 2 задания, а не другие. – Kirill

0

Если все, что вы хотите, это первые два результата, а затем отбросить ot ее задачи, вы можете дождаться завершения первых двух задач, а затем отменить остальные, например, вызывая shutdownNow, если вам больше не нужна служба завершения.

Future<Boolean> result1 = copmletionService.take(); 
Future<Boolean> result2 = copmletionService.take(); 
completionService.shutdownNow(); 
+1

Это не сработает. Когда я возьму два результата, некоторые другие задачи начнут выполняться, и все еще будет прерванное исключение – Kirill