捕获Java线程池执行任务抛出的异常

84浏览

	捕获Java线程池执行任务抛出的异常

Java中线程执行的任务接口要求不抛出Checked异常,那么如果run()方法中抛出了RuntimeException,将会怎么处理了?通常对象运行设置一个默认的异常处理方法:而这个默认的静态全局的异常捕获方法时输出堆栈。 当然,我们可以覆盖此默认实现,只需要一个自定义的接口实现即可。

而在线程池中却比较特殊。

默认情况下,线程池会Catch住所有异常,当任务执行完成((Callable))获取其结果时(())会抛出此RuntimeException。

其中ExecutionException异常即是或者抛出的异常。 也就是说,线程池在执行任务时捕获了所有异常,并将此异常加入结果中。

这样一来线程池中的所有线程都将无法捕获到抛出的异常。 从而无法通过设置线程的默认捕获方法拦截的错误异常。 也不同通过来完成异常的拦截。

好在预留了一个方法,运行在任务执行完毕进行扩展(当然也预留一个protected方法beforeExecute(Threadt,Runnabler)):protectedvoidafterExecute(Runnabler,Throwablet){}此方法的默认实现为空,这样我们就可以通过继承或者覆盖ThreadPoolExecutor来达到自定义的错误处理。 解决办法如下:此办法的关键在于,事实上afterExecute并不会总是抛出异常Throwablet,通过查看源码得知,异常是封装在此时的Future对象中的,而此Future对象其实是一个的实现,默认的run方法其实调用的()。 innerRun(){(!compareAndSetState(0,RUNNING)){runner=();(getState()==RUNNING)innerSet(());releaseShared(0);}(Throwableex){innerSetException(ex);}}innerSetException(Throwablet){(;;){s=getState();(s==RAN)(s==CANCELLED){releaseShared(0);}(compareAndSetState(s,RAN)){exception=t;result=releaseShared(0);done();}}}这里我们可以看到它吃掉了异常,将异常存储在的exception字段中:当我们获取异步执行的结果时,()()异常就会被包装成ExecutionException异常抛出。

也就是说当我们想线程池ThreadPoolExecutor()提交任务时,如果不理会任务结果(()),那么此异常将被线程池吃掉。 而是继承ThreadPoolExecutor的,因此情况类似。

结论,通过覆盖方法,我们才能捕获到任务的异常(RuntimeException)。

原文地址:2009-2014IMXYLZ|。

您现在的位置:情感 > 情感障碍

上一篇:幼儿园大班教案《小刺猬烫发》含反思

下一篇:没有了

你可能喜欢的:
友情链接