捕获Java线程池执行任务抛出的异常 futrue获取结果异常情况

您所在的位置:网站首页 多线程如何获取子线程的执行结果 捕获Java线程池执行任务抛出的异常 futrue获取结果异常情况

捕获Java线程池执行任务抛出的异常 futrue获取结果异常情况

2024-07-14 22:46| 来源: 网络整理| 查看: 265

1:submit(Callable task)

submit方便Exception处理:

There is a difference when looking at exception handling. If your tasks throws an exception and if it was submitted with execute this exception will go to the uncaught exception handler (when you don't have provided one explicitly, the default one will just print the stack trace to System.err). If you submitted the task with submit any thrown exception, checked or not, is then part of the task's return status. For a task that was submitted with submit and that terminates with an exception, the Future.get will rethrow this exception, wrapped in an ExecutionException.   意思就是如果你在你的task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理, 那么就需要用到submit,通过捕获Future.get抛出的异常。

public interface ExecutorService extends Executor { ...省略 Future submit(Callable task);

好在java.util.concurrent.ThreadPoolExecutor 预留了一个方法,运行在任务执行完毕进行扩展(当然也预留一个protected方法beforeExecute(Thread t, Runnable r)):

protected void afterExecute(Runnable r, Throwable t) { }

此方法的默认实现为空,这样我们就可以通过继承或者覆盖ThreadPoolExecutor 来达到自定义的错误处理。

解决办法如下:

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(11, 100, 1, TimeUnit.MINUTES, // new ArrayBlockingQueue(10000),// new DefaultThreadFactory()) { protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); printException(r, t); } }; private static void printException(Runnable r, Throwable t) { if (t == null && r instanceof Future) { try { Future future = (Future) r; if (future.isDone()) future.get(); } catch (CancellationException ce) { t = ce; } catch (ExecutionException ee) { t = ee.getCause(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // ignore/reset } } if (t != null) log.error(t.getMessage(), t); }

为什么重写protected void afterExecute(Runnable r, Throwable t) { }方法就可以获取具体异常呢?

答:百度ThreadPoolExcutor源码解析 

https://www.jianshu.com/p/96772777749b

或者不用重写该方法,直接在future.get()的时候 加上try catch

最后核心的是:

每个线程在执行的时候,都会把发生的异常catch住,然后 交给afterExecute(task, thrown); 如果重写了该方法,可以自行处理,如果没重写该方法,会向外抛出,在future.get()的时候 自行捕获即可。

final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt 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(); } 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, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }

 

public class ThreadPoolExecutor extends AbstractExecutorService { ...省略 protected void afterExecute(Runnable r, Throwable t) { }

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3