Остановить Executor, когда Callable возвращает определенный результат

Я хотел бы запретить исполнителю запускать какие-либо объекты Future, даже если они были отправлены исполнителю. Запуск нескольких потоков через Executor работает нормально, но Executor должен остановиться, когда один из Callable возвращает логическое значение TRUE. Хорошо, что текущая запущенная версия Future завершена, но продолжать остальное было бы пустой тратой времени.

Set<Future<Boolean>> calculationSet = new HashSet<Future<Boolean>>();
threadPool = Executors.newFixedThreadPool(3);

int x = nextX();
int y = nextY();

do {
   Callable<Boolean> mathCalculation = new MathCalculation(x, y);
   Future<Boolean> futureAttempt = threadPool.submit(mathCalculation);
   calculationSet.add(futureAttempt);

   x = nextX();
   y = nextY();
} while (runSomeMore());

Где MathCalculation реализует интерфейс Callable, а его метод call() возвращает логическое значение.

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


person Forage    schedule 09.02.2011    source источник


Ответы (2)


Вы также можете использовать ExecutorCompletionService

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html

В верхней части этого JavaDoc есть два примера, а второй говорит:

"Предположим... вы хотите использовать первый ненулевой результат набора задач, игнорируя любые исключения, которые встречаются с исключениями, и отменяя все остальные задачи, когда первая будет готова:", затем пример кода.

Тан звучит многообещающе, решает ли он вашу проблему?

person Arnost Valicek    schedule 09.02.2011
comment
Оказалось именно то, что мне было нужно. Спасибо. Мне пришлось внести некоторые коррективы, чтобы предотвратить нехватку памяти, но теперь это работает как шарм. - person Forage; 10.02.2011

Если вы хотите, чтобы вызываемый объект останавливал службу исполнителя, я предлагаю вам создать оболочку или изменить вызываемый объект, чтобы сделать это.

// performs a threadPool.shutdownNow() as required.
new MathCalculation(x, y, threadPool) 
person Peter Lawrey    schedule 09.02.2011
comment
Хе-хе, это слишком просто! Я попробовал, и да, это сработало, но в конце концов мне пришлось переключиться на использование ExecutorCompletionService. Использование последнего позволяет очищать ресурсы сразу после завершения потока. Если этого не сделать, через некоторое время возникнут исключения OutOfMemory. - person Forage; 10.02.2011