将异常对象赋予outcome?有什么用呢?这个outcome?是什么呢?当我们使用submit返回Future对象,并使用Future.get()时,会调用内部的report方法!
public V get() throws InterruptedException, ExecutionException {int s = state;if (s <= COMPLETING)s = awaitDone(false, 0L);//注意这个方法return report(s);}
reoport里面实际上返回的是outcome ,刚好之前的异常就set到了这个outcome里面
private V report(int s) throws ExecutionException { //设置`outcome`Object x = outcome;if (s == NORMAL)//返回`outcome`return (V)x;if (s >= CANCELLED)throw new CancellationException();throw new ExecutionException((Throwable)x);}
因此,在用submit提交的时候,runable对象被封装成了future ,future 里面的 run方法在处理异常时, try-catch?了所有的异常,通过setException(ex);?方法设置到了变量outcome里面,可以通过future.get获取到outcome 。
所以在submit提交的时候,里面发生了异常,是不会有任何抛出信息的 。而通过future.get()?可以获取到submit抛出的异常!在submit里面,除了从返回结果里面取到异常之外, 没有其他方法 。因此,在不需要返回结果的情况下,最好用execute ,这样就算没有写try-catch,疏漏了异常捕捉,也不至于丢掉异常信息 。
方案三:重写afterExecute进行异常处理通过上述源码分析,在excute的方法里面,可以通过重写afterExecute?进行异常处理,但是注意! 这个也只适用于excute提交(submit的方式比较麻烦,下面说),因为submit的task.run?里面把异常吞了,根本不会跑出来异常,因此也不会有异常进入到afterExecute里面 。
在runWorker?里面,调用task.run之后,会调用线程池的 afterExecute(task, thrown) 方法
final void runWorker(Worker w) {//当前线程Thread wt = Thread.currentThread();//我们的提交的任务Runnable task = w.firstTask;w.firstTask = null;w.unlock(); // allow interruptsboolean completedAbruptly = true;try {while (task != null || (task = getTask()) != null) {w.lock();if ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() &&runStateAtLeast(ctl.get(), STOP))) &&!wt.isInterrupted())wt.interrupt();try {beforeExecute(wt, task);Throwable thrown = null;try {//直接就调用了task的run方法task.run(); //如果是futuretask的run,里面是吞掉了异常,不会有异常抛出,// 因此Throwable thrown = null;也不会进入到catch里面} catch (RuntimeException x) {thrown = x; throw x;} catch (Error x) {thrown = x; throw x;} catch (Throwable x) {thrown = x; throw new Error(x);} finally {//调用线程池的afterExecute方法 传入了task和异常afterExecute(task, thrown);}} finally {task = null;w.completedTasks++;w.unlock();}}completedAbruptly = false;} finally {processWorkerExit(w, completedAbruptly);}}
重写afterExecute处理execute提交的异常
public class ThreadPoolException3 {public static void main(String[] args) throws InterruptedException, ExecutionException {//1.创建一个自己定义的线程池ExecutorService executorService = new ThreadPoolExecutor(2,3,0,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(10)) {//重写afterExecute方法@Overrideprotected void afterExecute(Runnable r, Throwable t) {System.out.println("afterExecute里面获取到异常信息,处理异常" + t.getMessage());}};//当线程池抛出异常后 executeexecutorService.execute(new task());}}class task3 implements Runnable {@Overridepublic void run() {System.out.println("进入了task方法!!!");int i = 1 / 0;}}
执行结果:我们可以在afterExecute方法内部对异常进行处理
文章插图
如果要用这个afterExecute?处理submit提交的异常,要额外处理 。判断Throwable?是否是FutureTask,如果是代表是submit提交的异常,代码如下:
public class ThreadPoolException3 {public static void main(String[] args) throws InterruptedException, ExecutionException {//1.创建一个自己定义的线程池ExecutorService executorService = new ThreadPoolExecutor(2,3,0,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(10)) {//重写afterExecute方法@Overrideprotected void afterExecute(Runnable r, Throwable t) {//这个是excute提交的时候if (t != null) {System.out.println("afterExecute里面获取到excute提交的异常信息,处理异常" + t.getMessage());}//如果r的实际类型是FutureTask 那么是submit提交的,所以可以在里面get到异常if (r instanceof FutureTask) {try {Future<?> future = (Future<?>) r;//get获取异常future.get();} catch (Exception e) {System.out.println("afterExecute里面获取到submit提交的异常信息,处理异常" + e);}}}};//当线程池抛出异常后 executeexecutorService.execute(new task());//当线程池抛出异常后 submitexecutorService.submit(new task());}}class task3 implements Runnable {@Overridepublic void run() {System.out.println("进入了task方法!!!");int i = 1 / 0;}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 霍启刚|霍启刚:因失去3千亿继承权,遭前任抛弃,郭晶晶为何还甘愿嫁他
- 小三|死循环!“山东第一胖”王浩楠翻车后又复胖,体重反弹疑已被抛弃
- 品如|抛弃艾莉,背叛林品如,洪世贤为何最后会爱上“高珊珊”
- 章泽天|29岁章泽天二胎得子!孩子获英国籍,刘强东抛下妻儿回国返工
- 秸秆禁烧宣传标语大全?三夏禁烧禁抛秸秆宣传标语?
- 看懂CPU核心线程数不被骗
- 禁止高空抛物卡通图片?禁止高空抛物的温馨提示是什么?
- 你是我挣扎过放弃过 你为什么抛弃我
- 姐姐|即将撕破脸,《红气球》第11集:姐姐妹妹都在被抛弃的边缘疯狂
- 狂飙|《狂飙》女三号出圈告诉:除了剧抛脸,重视气场的穿搭也是加分项