为什么并行ForkJoinPool会使我的异常倍增?
假设我有如下代码:
Future<Object> executeBy(ExecutorService executor) { return executor.submit(() -> {
throw new IllegalStateException();
});
}
使用ForkJoinPool#commonPool
时没有问题,但是当我使用并行时ForkJoinPool
它会加倍IllegalStateException
。例如:
executeBy(new ForkJoinPool(1)).get(); // ^--- double the IllegalStateException
:为什么并行性会在其中发生ForkJoinPool
两倍?Exception``Callable
:如何避免这种奇怪的行为?
回答:
如果在工作线程中引发了异常,则Fork /
Join池通常会尝试在调用者线程内重新创建异常,并将原始异常设置为其原因。这就是您认为的“加倍”。当您仔细查看堆栈跟踪时,您会注意到这两个异常之间的差异。
公用池在这方面没有什么不同。但是公共池允许调用者线程在等待最终结果时参与工作。因此,当您将代码更改为
static Future<Object> executeBy(ExecutorService executor) { return executor.submit(() -> {
throw new IllegalStateException(Thread.currentThread().toString());
});
}
您会注意到,经常发生的情况是,调用者线程get()
在该方法中的调用速度更快,并且在该方法中进行工作窃取的速度超过了工作线程可以接任务的速度。换句话说,您的供应商已在主线程/调用者线程中执行,在这种情况下,不会重新创建异常。
可以通过抛出一个异常类型来轻松禁用此功能,该异常类型没有F / J可以使用的匹配公共构造函数,例如下面这个整洁的内部类:
static Future<Object> executeBy(ExecutorService executor) { return executor.submit(() -> {
throw new IllegalStateException() {
@Override
public String toString() {
String s = getClass().getSuperclass().getName();
String message = getLocalizedMessage();
return message!=null? s+": "+message: s;
}
};
});
}
以上是 为什么并行ForkJoinPool会使我的异常倍增? 的全部内容, 来源链接: utcz.com/qa/425161.html