Java“终结”线程异常
我正在使用多个线程对大型数据集进行一些繁重(且容易出错)的处理。我要求所有线程都完成执行,无论它们是抛出异常还是正常终止(不返回任何值),然后程序才能继续。我使用 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
类型为 < code>ThreadPoolExecutor$Worker,而不是JobManager
类型,这会阻止我调用“finalizer”方法。使用自定义
ExecutorService
并重写afterExecute(Runnable r, Throwable t)
方法。这与 1 存在相同的问题。将整个
JobManager#doWork()
包装在catch
语句中,并使用返回值来指示是否抛出异常。然后,我可以提交
作业并使用FutureTask#get()
来确定是否引发异常。我不喜欢这个解决方案,因为当你有一个复杂的异常机制时,我觉得返回代码是错误的工具。此外,get()
会等待(除非被中断),这意味着我无法立即处理其他线程中的错误。摆脱
CountDownLatch
。将所有Future
存储在一个列表中,并反复插入,直到我对状态满意为止。这可能有效,但感觉像是一个肮脏的黑客。
非常感谢任何建议。
I am using several threads to do some heavy (and error-prone) processing on a large data set. I require all threads to finish execution, regardless of whether they throw an exception or terminate normally (no value is returned), before the program can continue. I am using a CountDownLatch
to achieve this, and an ExecutorService
to actually run the jobs. I want the worker threads (let's call them JobManager
-s for the sake of argument) to notify the latch even if they throw an exception. A JobManager
can take anywhere between a second and an hour to complete, and may fail at any time. The idea is to invoke the "finalizer" method of JobManager
if an exception is thrown. Now, the ExecutorService
likes to catch exceptions or to conceal the true origin of the ones it does not. I have though of a few ways around this, neither of which is satisfactory:
Use
ExecutorService#execute(Runnable r)
rather thansubmit(Runnable r)
. I can do that since I do not care about the return value of theJobManager
. I have provided a customThreadFactory
, which attaches anUncaughtExceptionHandler
to each newly created thread. The problem with this approach is that whenUncaughtExceptionHandler#uncaughtException(Thread t, Throwable e)
is invoked,t
'sRunnable
is of typeThreadPoolExecutor$Worker
, and not of typeJobManager
, which prevents me from invoking the "finalizer" method.Use a custom
ExecutorService
and override theafterExecute(Runnable r, Throwable t)
method. This suffers from the same problem as 1.Wrap the whole
JobManager#doWork()
in acatch
statement and use the return value to indicate if an exception was thrown. I can thensubmit
the jobs and useFutureTask#get()
to decide if an exception was thrown. I do not like this solution because I feel return codes the wrong tool when you have an elaborate exception mechanism. Moreover,get()
will wait (unless interrupted), which means I cannot handle errors in other threads immediately.Get rid of the
CountDownLatch
. Store allFuture
s in a list and repeatedly poke in until I am satisfied with the states. This might work, but feels like a dirty hack.
Any suggestions are greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
据我了解,您可以使用一个简单的
try
-finally
块:As far as I understand, you can use a simple
try
-finally
block: