首页 > 科技 >

Java线程池「异常处理」正确姿势:有病就得治

2019-07-12 12:15:53 暂无 阅读:1318 评论:0
Java线程池「异常处理」正确姿势:有病就得治

问题剖析

我们来看一下java中的线程池是若何运行我们提交的义务的,具体流程对照复杂,这里我们不存眷,我们只存眷义务执行的部门。java中的线程池用的是ThreadPoolExecutor,真正执行代码的部门是runWorker方式:final void runWorker(Worker w)

Java线程池「异常处理」正确姿势:有病就得治

能够看到,法式会捕捉包罗Error在内的所有非常,而且在法式最后,将显现过的非常和当前义务传递给afterExecute方式。

而ThreadPoolExecutor中的afterExecute方式是没有任何实现的。

protected void afterExecute(Runnable r, Throwable t) { }存在问题

想象下ThreadPoolExecutor这种处理体式会有什么问题?

如许做可以包管我们提交的义务抛出了非常不会影响其他义务的执行,同时也不会对用来执行该义务的线程发生任何影响。

问题就在afterExecute方式上, 这个方式没有做任何处理,所以若是我们的义务抛出了非常,我们也无法马上感知到。 即使感知到了,也无法查察非常信息。

所以,作为一名好的斥地者,是不该该许可这种情形显现的。若何避免这种问题

思路很简洁。

在提交的义务中将非常捕捉并处理,不抛给线程池。

非常抛给线程池,然则我们要实时处理抛出的非常。

1、直接catch

第一种思路很简洁,就是我们提交义务的时候,将所有或者的非常都Catch住,而且本身处理。

说白了就是把买卖逻辑都trycatch起来。 然则这种思路的瑕玷就是:

所有的分歧义务类型都要trycatch,增加了代码量。

不存在checkedexception的处所也需要都trycatch起来,代码丑恶。

2、线程池实现

第二种思路就能够避免上面的两个问题。

第二种思路又有以下四种实现体式

(1)自界说线程池

自界说线程池,继续ThreadPoolExecutor并复写其afterExecute(Runnable r, Throwable t)方式。

Java线程池「异常处理」正确姿势:有病就得治

(2)实现Thread.UncaughtExceptionHandler接口

实现Thread.UncaughtExceptionHandler接口,实现void uncaughtException(Thread t, Throwable e);方式,并将该handler传递给线程池的ThreadFactory

Java线程池「异常处理」正确姿势:有病就得治

(3)继续ThreadGroup

笼盖其uncaughtException方式。(与第二种体式雷同,因为ThreadGroup类自己就实现了Thread.UncaughtExceptionHandler接口)尤其注重:上面三种体式针对的都是经由execute(xx)的体式提交义务,若是你提交义务用的是submit()方式,那么上面的三种体式都将不起感化,而应该使用下面的体式

Java线程池「异常处理」正确姿势:有病就得治

(4)采用Future模式

若是提交义务的时候使用的方式是submit,那么该方式将返回一个Future对象,所有的非常以及处理究竟都能够经由future对象获取。 采用Future模式,将返回究竟以及非常放到Future中,在Future中处理

Java线程池「异常处理」正确姿势:有病就得治

总结

非常处理是java中非常主要的流程,然则线程池的默认把持,会使的这些内容被静沉寂的忽略,这在某些情形下是致命的。

本文商量了从用户层面的代码到线程池层面的各类革新方式,力求让买卖代码加倍坚固可控。

相关文章