为什么并行性ForkJoinPool加倍我的exception?
假设我有如下代码:
Future executeBy(ExecutorService executor) { return executor.submit(() -> { throw new IllegalStateException(); }); }
使用ForkJoinPool#commonPool
时没有问题,但是当我使用并行性ForkJoinPool
它会使IllegalStateException
加倍。 例如:
executeBy(new ForkJoinPool(1)).get(); // ^--- double the IllegalStateException
Q1 :为什么ForkJoinPool
将Exception
发生在Callable
?
Q2 :如何避免这种奇怪的行为?
如果在工作线程中抛出exception并将原始exception设置为其原因,则Fork / Join池通常会尝试在调用者的线程内重新创建exception。 这就是你所认为的“倍增”。 当您仔细观察堆栈跟踪时,您会注意到这两个exception之间的区别。
在这方面,共同池没有什么不同。 但是公共池允许调用者线程在等待最终结果时参与工作。 所以当你改变代码时
static Future
你会注意到,调用者线程调用get()
并在该方法中进行工作窃取比工作线程可以接收任务更快。 换句话说,您的供应商已在主/调用者线程中执行,在这种情况下,将不会重新创建exception。
通过抛出一个没有F / J可以使用的匹配公共构造函数的exception类型,可以很容易地禁用此function,就像这个整洁的内部类一样:
static Future
ForkJoinPool
创建ForkJoinTask
实例以执行您的提交。
ForkJoinTask
尝试在发生exception时提供准确的堆栈跟踪。 它的javadoc说
Rethrownexception的行为与常规exception的行为相同,但是,如果可能,包含启动计算的线程以及实际遇到exception的线程的堆栈跟踪(例如使用
ex.printStackTrace()
); 最低限度只有后者。
这是此行为的private
实现中的注释
/** * Returns a rethrowable exception for the given task, if * available. To provide accurate stack traces, if the exception * was not thrown by the current thread, we try to create a new * exception of the same type as the one thrown, but with the * recorded exception as its cause. If there is no such * constructor, we instead try to use a no-arg constructor, * followed by initCause, to the same effect. If none of these * apply, or any fail due to other exceptions, we return the * recorded exception, which is still correct, although it may * contain a misleading stack trace. * * @return the exception, or null if none */ private Throwable getThrowableException() {
换句话说,它接受你的代码抛出的IllegalStateException
,找到接收Throwable
的IllegalStateException
的Throwable
函数,调用具有原始IllegalStateException
作为其参数的构造函数,并返回结果(然后在ExecutionException
重新IllegalStateException
)。
您的堆栈跟踪现在还包含get
调用的堆栈跟踪。
使用ForkJoinPool
作为您的ExecutorService
,我不相信您可以避免它,它取决于当前线程和抛出的exception类型中可用的构造函数是否抛出exception。
- Android SQLite如何获取特定列:行值
- org.hibernate.LazyInitializationException:无法初始化代理 – 没有会话
- Java Arraylist得到了java.lang.IndexOutOfBoundsException?
- 在Exception上转储变量的状态
- 哪个更好/更有效:检查错误值或捕获Java中的exception
- 系统exception与应用程序exception的明确说明
- 在预期时处理NumberFormatException的正确方法是什么?
- Java / C#中检查的exception是什么?
- Java Jackson:反序列化复杂的多态对象模型:JsonMappingException:意外的令牌(START_OBJECT),预期的VALUE_STRING