java线程池中任务异常处理
来源:互联网 发布:timeline js 编辑:程序博客网 时间:2024/06/11 23:03
首先我们看个例子,当使用线程池执行任务时如果某个任务出现异常会是什么效果
import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class DivTask implements Runnable { int a,b; @Override public void run() { System.out.println(a/b); } public DivTask(int a, int b) { super(); this.a = a; this.b = b; } public static void main(String[] args) { ThreadPoolExecutor pools=new ThreadPoolExecutor(0, 10, 0,TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); for(int i=0;i<5;i++){ pools.submit(new DivTask(100,i)); } }}运行结果1005025
你会发现少了一个结果输出,这个缺失的原因是由于i=0导致的,但是系统却一点错误提示都没有,后面如果使用在复杂的业务场景中,那么出现这种错误去排查起来可就困难了
解决办法
1. 将sumit()方法换成execute()执行,即pools.execute(new DivTask(100,i));而且一个任务的异常对其他任务的执行不会造成任何影响
2. 使用改造submit(),使用future.get()获取异常信息
Future future=pools.submit(new DivTask(100,i));future.get();运行结果如下Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188) at threadpool.DivTask.main(DivTask.java:26)Caused by: java.lang.ArithmeticException: / by zero at threadpool.DivTask.run(DivTask.java:15) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:744)
我们发现异常信息虽能正常打印出来,可仔细看,却发现异常却发现只知道异常是从哪里抛出,不知道这个产生异常的任务是从哪里提交的,任务的具体提交位置已经被线程池完全淹没了,我们只能看到线程池的调度流程,这对于我们排查错误造成很大的困难。
如何详细的打印出线程池中提交的任务所抛出的异常信息
1. 在提交的任务中将异常捕获,不抛给线程池
//其实就是将所有的业务逻辑都使用try...catch起来,但是这种办法感觉很low,代码量增加不少,不推荐@Override public void run() { try { //处理所有的业务逻辑 } catch (Throwable e) { //打印日志等 } finally { //其他处理 } }
2.自定义线程池,execute()、submit()方法,在调用这些方法前,对任务进行一次包装然后再提交,实际上也是第一种方法的思路,只是不用在每个run()都去try catch处理异常
public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor pools=new ThreadPoolExecutor(0, 10, 0,TimeUnit.SECONDS,new SynchronousQueue<Runnable>()){ private Runnable warp(final Runnable task,final Exception clientStack, String clientThreadName){ return new Runnable() { @Override public void run() { try { task.run(); } catch (Exception e) { clientStack.printStackTrace(); throw e; } } }; } private Exception clientTrace(){ return new Exception("client stack trace"); } @Override public void execute(Runnable command) { // TODO Auto-generated method stub super.execute(warp(command,clientTrace(), Thread.currentThread().getName())); } @Override public Future<?> submit(Runnable task) { return super.submit(warp(task,clientTrace(),Thread.currentThread().getName())); } }; for(int i=0;i<5;i++){ pools.execute(new DivTask(100,i)); } }
运行结果
100332550java.lang.Exception: client stack trace at threadpool.DivTask$1.clientTrace(DivTask.java:39) at threadpool.DivTask$1.execute(DivTask.java:44) at threadpool.DivTask.main(DivTask.java:52)Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero at threadpool.DivTask.run(DivTask.java:16) at threadpool.DivTask$1$1.run(DivTask.java:30) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:744)
为什么现在能定位出异常任务是在哪里提交的,关键点就在于我们在submit()中传入了一个自定义的Exception。一旦任务有异常,我们就会将此异常抛出,这样我们就能定位是哪里submit的了.
1 0
- java线程池中任务异常处理
- java线程池异常处理
- Java 线程异常处理
- Java 线程池的异常处理机制
- 【捕获Java线程池执行任务抛出的异常】
- 捕获Java线程池执行任务抛出的异常
- Java线程池执行的任务抛出异常看不到日志
- java线程异常的处理
- Java 多线程-线程异常处理
- Java中异常处理
- Java中异常处理
- java中异常处理
- java中异常处理
- Java中异常处理
- Java中异常处理
- java中处理异常
- java中异常处理
- 多任务处理:线程池
- RTEMS 源文件coding conventions
- 一些基本流的使用和线程讲解
- 哈佛结构和冯·诺依曼结构的区别
- 【二】软考—递归
- BeautifulSoup
- java线程池中任务异常处理
- # ajax #
- Building Apps with Location & Maps
- try-catch-finally结构体的简要说明
- iOS之类方法load和initialize
- 使用SLM方法降低PAPR
- 爬取豆瓣影评数据
- java学习(14)
- 使用Dom4j解析xml文件