使用ForkJoinPool
提交任务(RecursiveAction
或RecursiveTask
)时处理异常(未捕获)的更好方法是什么?
当WorkerThread突然终止(无论如何不在我们的控制之下)时,ForkJoinPool接受Thread.UncaughtExceptionHandler
来处理异常,但当ForkJoinTask
抛出异常时不使用此处理程序。我在实施中使用标准submit
/ invokeAll
方式。
以下是我的情景:
我有一个Thread在无限循环中运行,从第三方系统读取数据。在此线程中,我将任务提交到ForkJoinPool
new Thread() { public void run() { while (true) { ForkJoinTask<Void> uselessReturn = ForkJoinPool.submit(RecursiveActionTask); } } }
我正在使用RecursiveAction,在少数情况下使用RecursiveTask。这些任务使用submit()
方法提交给FJPool。
我希望有一个类似于UncaughtExceptionHandler
的通用异常处理程序,如果一个Task抛出一个未经检查/未捕获的异常,我可以处理异常并在需要时重新提交任务。处理异常还可确保在一个/某些任务抛出异常时排队的任务不会被取消。
invokeAll()
方法返回一组ForkJoinTasks,但这些任务位于递归块中(每个任务调用compute()
方法,可以进一步拆分[假设场景])
class RecursiveActionTask extends RecursiveAction {
public void compute() {
if <task.size() <= ACCEPTABLE_SIZE) {
processTask() // this might throw an checked/unchecked exception
} else {
RecursiveActionTask[] splitTasks = splitTasks(tasks)
RecursiveActionTasks returnedTasks = invokeAll(splitTasks);
// the below code never executes as invokeAll submits the tasks to the pool
// and the flow never comes to the code below.
// I am looking for some handling like this
for (RecusiveActionTask task : returnedTasks) {
if (task.isDone()) {
task.getException() // handle this exception
}
}
}
}
}
我注意到当3-4个任务失败时,整个队列提交单元被丢弃。目前我已经在我个人不喜欢的过程任务中添加try/catch
。我正在寻找更通用的。
get()
方法更有可能使我的流顺序等待任务完成。如何处理上述场景中的异常?
答案 0 :(得分:2)
这表明我们在Akka解决了这个问题:
/**
* INTERNAL AKKA USAGE ONLY
*/
final class MailboxExecutionTask(mailbox: Mailbox) extends ForkJoinTask[Unit] {
final override def setRawResult(u: Unit): Unit = ()
final override def getRawResult(): Unit = ()
final override def exec(): Boolean = try { mailbox.run; true } catch {
case anything ⇒
val t = Thread.currentThread
t.getUncaughtExceptionHandler match {
case null ⇒
case some ⇒ some.uncaughtException(t, anything)
}
throw anything
}
}