Я пытаюсь выполнить несколько задач параллельно с CompletionService. Проблемы возникают, когда я пытаюсь осуществить отмену.Future.cancel (true) не надежно отменяет/прерывает поток
Вот набросок кода я использую:
void startTasks(int numberOfTasks) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
CompletionService<TaskResultType> completionService = new ExecutorCompletionService<TaskResultType>(executor);
ConcurrentLinkedQueue<TaskResultType> results = new ConcurrentLinkedQueue<BenchmarkResult>();
ArrayList<Future> futures = new ArrayList<Future>();
for (int i = 0; i < numberOfTasks ; i++) {
TypeOfTask task = ... ;
Future future = completionService.submit(task);
futures.add(future);
}
boolean failed = false;
Throwable cause = null;
for (int i = 0; i < numberOfThreads; i++) {
try {
Future<TaskResultType> resultFuture = completionService.take();
TaskResultType result = resultFuture.get();
results.add(result);
} catch (ExecutionException e) {
failed = true;
cause = e.getCause();
/* cancel all other running tasks in case of failure in one task */
for (Future future : futures) {
future.cancel(true);
}
} catch (CancellationException e) {
// consume (planned cancellation from calling future.cancel())
}
}
executor.shutdown();
// code to throw an exception using cause
}
Задачи реализации Callable
.
Когда я сейчас делаю исключение в одной из задач в большинстве случаев, это отлично работает, то есть я сразу получаю исключения от других задач и задач, которые заканчиваются немедленно (позволяет вызвать этот случай A). Но иногда (позволяет называть этот случай B), некоторые из задач заканчиваются первым, а затем бросают исключение CancellationException. Функция Future.cancel (true) вернулась в обоих случаях в обоих случаях для всех задач (кроме тех, которые были с исходным ExecutionException, потому что этот уже был отменен).
Я проверяю прерванный флаг с помощью Thread.currentThread.isInterrupted() в завершаемых задачах (т. Е. В тех случаях, когда аннулирование завершается неудачно), прерванный флаг имеет значение false.
Все это кажется очень странным поведением в моих глазах. Кто-нибудь может понять, в чем проблема?
Update
Лучшая идея до сих пор у меня есть, что где-то глубоко внутри кода, включающего задачу (только часть кода высокого уровня от себя) прерванное состояние потребляемый, например, с помощью уловленного InterruptedException, который не вызывает Thread.interrupt(), чтобы восстановить статус. Точное время, когда прерванный флаг задается функцией Future.cancel(), может незначительно отличаться из-за планирования потоков, что объясняет непоследовательное поведение. Будет ли потребленный прерванный статус объяснять поведение случая B?
Как вы можете проверить прерванный флаг в задании, которое уже выполнено? Если он уже завершен, код не работает, правильно? – Gray
Не видя кода в своей Задаче, мы не можем помочь вам – dkatzel
Я подозреваю, что ваша проблема в том, что одна из задач выполняет IO или иным образом заблокирована и не проверяет 'Thread.currentThread.isInterrupted()'. Поэтому, даже если вы отменили «Будущее», и поток прерывается, это не обнаруживается. Ваша программа зависает или заканчивается? Если он зависает, вы можете сделать дамп потока, чтобы увидеть, какой из потоков зависает? – Gray