[英]Java “finalize” thread on exception
我正在使用多个线程对大型数据集进行一些繁重(且容易出错)的处理。 我要求所有线程都可以完成执行,无论它们是否引发异常或正常终止(不返回任何值),然后程序才能继续执行。 我正在使用CountDownLatch
实现此目的,并使用ExecutorService
实际运行作业。 我希望工作线程(为方便起见,我们称它们为JobManager
-s)即使它们抛出异常也要通知闩锁。 JobManager
可能需要一秒钟到一个小时才能完成,并且随时可能失败。 这个想法是如果抛出异常,则调用JobManager
的“ finalizer”方法。 现在, ExecutorService
喜欢捕获异常或隐藏不包含的异常的真实来源。 我有几种解决方法,但都不令人满意:
使用ExecutorService#execute(Runnable r)
而不是submit(Runnable r)
。 我可以这样做,因为我不在乎JobManager
的返回值。 我提供了一个自定义ThreadFactory
,它将UncaughtExceptionHandler
附加到每个新创建的线程。 这种方法的问题在于,当调用UncaughtExceptionHandler#uncaughtException(Thread t, Throwable e)
, t
的Runnable
类型是ThreadPoolExecutor$Worker
,而不是JobManager
类型,这阻止了我调用“ finalizer”方法。
使用自定义的ExecutorService
并重写afterExecute(Runnable r, Throwable t)
方法。 这遭受与1相同的问题。
将整个JobManager#doWork()
包装在catch
语句中,并使用返回值指示是否引发了异常。 然后,我可以submit
作业并使用FutureTask#get()
来确定是否引发了异常。 我不喜欢这种解决方案,因为当您拥有精心设计的异常机制时,我觉得返回码是错误的工具。 而且, get()
将等待(除非被中断),这意味着我无法立即处理其他线程中的错误。
摆脱CountDownLatch
。 将所有Future
都存储在列表中,并反复戳入,直到对状态感到满意为止。 这可能有效,但感觉像是一个肮脏的hack。
任何建议,不胜感激。
据我了解,您可以使用一个简单的try
- finally
块:
public class JobManager {
public void doWork() {
try {
...
} finally {
countDownLatch.countDown();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.