ExecuterService submit
起因
在线上排查问题时,请求不成功,但是日志里面没有找到任何异常。
重现
写如下测试代码,发现 test1、test2 会直接抛出异常,test3 没有抛出异常,test4 在 16 行才抛出异常。
private static ExecutorService es = Executors.newSingleThreadExecutor();
public static void main(String[] args) throws InterruptedException, ExecutionException {
// test1
new Thread(() -> { throw new RuntimeException("in thread start");}).start();
// test2
es.execute(() -> { throw new RuntimeException("in execute");});
// test3
es.submit(() -> { throw new RuntimeException("in submit");});
// test4
Future<Object> future = es.submit(() -> { throw new RuntimeException("in submit"); });
Thread.sleep(1000);
future.get();
es.shutdown();
}输出如下:
原因
execute
使用 ThreadPoolExecutor.execute 执行任务时,任务原封不动提交给 Worker,若任务抛出异常,Worker 会直接再次抛出:
submit
使用 ThreadPoolExecutor.submit 执行任务时,任务会被封装成 FutureTask,FutureTask 的 run 方法会捕获异常,不会再次抛出,在 get 时才会抛出:
解决方案
方案1 - 选择 execute
若提交任务后,不需要获取返回结果,则尽量使用 execute 方法,这样就能在标准输出打印异常栈。
缺点:只能在标准输出打印异常栈,不能在日志系统里面打印,所以日志文件中还是没有异常输出。
方案2 - 从任务出发
自定义任务接口 Task,所有任务都实现 Task:
输出如下:
方案3 - 从线程池出发
自定义线程池继承 ThreadPoolExecutor,重写 afterExecute 方法:
输出如下:
Last updated
Was this helpful?
