一个子线程抛出异常后立即返回主线程

str*_*cer 5 java multithreading exception executorservice

我正在使用Executors.newCachedThreadPool()invokeAll使用List of Callables来执行长时间运行的多线程处理.我的主线程被阻塞,直到所有线程完成,我可以处理返回的Futures invokeAll.但是invokeAll,如果其中一个Callable抛出异常并终止其他线程,我想立即返回.

使用execute而不是invokeAll阻塞第一个future.get()不需要是抛出execption的那个.

使用忙等待循环所有的期货和检查isDone()似乎也不是最好的方法.

Tom*_*icz 6

您可以使用更复杂的同步机制,如锁存器,障碍或信号量,但请查看ExecutorCompletionService.它是一个轻量级的包装器ExecutorService,允许您监听第一个完成的任务.这是一个简单的例子:

final ExecutorService executorService = Executors.newCachedThreadPool();
final ExecutorCompletionService<String> completionService = 
            new ExecutorCompletionService<String>(executorService);
for (int i = 0; i < 10; ++i) {
    completionService.submit(new Task());
}
completionService.take().get();
Run Code Online (Sandbox Code Playgroud)

代码非常简单.首先你executorServicecompletionService.之后你用它来一个接一个地提交任务.最后一行至关重要.它完成第一个任务并尝试检索结果.如果它抛出一个异常,它将在这里被重新抛出,包裹着ExecutionException:

try {
    completionService.take().get();
} catch (ExecutionException e) {
    e.getCause();       //this was thrown from task!
}
Run Code Online (Sandbox Code Playgroud)

在内部catch块中,您可以以某种方式处理异常,例如,取消剩余任务或关闭整个线程池.

当然,您可以通过拨打take()十次来等待所有任务完成.只要至少完成一项任务,每次调用都将被阻止.