#线程池中的一个线程异常了会被怎么处理?

估计很多人会是以下三点答案(me too):

1.抛异常出来并打印在控制台上

2.其他线程任务不受影响

3.异常线程会被回收

但是这里我先提前说一下以上三点不全对,下面我们来具体分析一下。

#话不多说用代码来证明

熟悉Executors线程池(本文线程池都是指Executors)都知道 有两种提交线程的方式execute和submit方式,下面将以这两种提交方式来验证。

贴个代码凑个数

public static void main(String[] args) {

ThreadPoolTaskExecutor executorService = buildThreadPoolTaskExecutor();

executorService.execute(() -> run("execute方法"));

executorService.submit(() -> run("submit方法"));

}

private static void run(String name) {

String printStr = "【thread-name:" + Thread.currentThread().getName() + ",执行方式:" + name+"】";

System.out.println(printStr);

throw new RuntimeException(printStr + ",出现异常");

}

private static ThreadPoolTaskExecutor buildThreadPoolTaskExecutor() {

ThreadPoolTaskExecutor executorService = new ThreadPoolTaskExecutor();

executorService.setThreadNamePrefix("(小罗技术笔记)-");

executorService.setCorePoolSize(5);

executorService.setMaxPoolSize(10);

executorService.setQueueCapacity(100);

executorService.setKeepAliveSeconds(10);

executorService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

executorService.initialize();

return executorService;

}

观看执行结果,诶好奇怪

execute执行方式抛出异常显示在控制台了。

submit执行方式啥都没有输出。

众所周知submit底层其实也是调用的execute,因此它也有异常只是处理方法不一样,它们的区别是:

1、execute没有返回值。可以执行任务,但无法判断任务是否成功完成。——实现Runnable接口

2、submit返回一个future。可以用这个future来判断任务是否成功完成。——实现Callable接口

那怎么拿到submit中的异常呢?还是用代码来说话

Future> result=executorService.submit(() -> run("submit方法"));

try {

result.get();

}catch (Exception e){

e.printStackTrace();

}

获取了一下submit方法的返回结果,发现有异常了和execute一样了,所以第一点抛异常出来并打印在控制台上不是全对的!

到这估计大家和我一样都有一个疑问了 ,为啥execute直接抛出异常,submit没有呢?

要知道这个答案就只能去翻源码看了

在java.util.concurrent.ThreadPoolExecutor#runWorker中抛出了运行异常:

在java.lang.ThreadGroup#uncaughtException进行了异常处理:

uncaughtException是什么,我也不知道,百度了一下说这个方法是JVM调用的,在线程中只需要指定我们想要的处理方式即可

说道这里你可能会吐槽说了这么多submit到底为啥没有直接抛出异常,到底是怎么处理了,不要慌我们再看源码找答案

看submit源码会发现,submit中传进来的task会被封装成一个FutureTask,然后再调用execute,最后返回FutureTask。

你会发现走的是execute方法,如下图,会发现此时的task已经是FutureTask,所以再去看一下FutureTask的run方法是咋写的。

异常被存起来了....,再看源码是怎么实现的

返回参数里面有一个状态state翻源码发现在report方法中同时用到outcom和state状态判断打个断点发现还真是,当state为3时抛出了异常。

同理在找寻一下report调用位置可以很明显发现是FutureTask中get方法调用了,结合上面可以很明确了submit提交时异常被存储在线程结果信息中,当调用get方法是判断线程运行结果状态,有异常就抛出存储的异常信息,因此submit运行异常我们只能用get方法来拿到。

#至于第二点我就不多说了,平时使用中就已经证明了!

#第三点线程出异常了不是被线程池回收嘛?

看源码我们知道线程运行最后总有一个processWorkerExit要执行,看看里面的实现

很神奇先删掉线程又再调用创建线程的方法,所以异常线程不是被回收,而是被删除了再创建一个新的顶替了。

到此线程池中的线程异常了会被怎么处理讲完了,总结一下就是:

1、execute方法,可以看异常输出在控制台,而submit在控制台没有直接输出,必须调用Future.get()方法时,可以捕获到异常。

2、一个线程出现异常不会影响线程池里面其他线程的正常执行。

3、线程不是被回收而是线程池把这个线程移除掉,同时创建一个新的线程放到线程池中。

4、还有源码是个好东西,答案都在里面,就是太难看懂了

Java线程池线程突然没了_70%人答不全!线程池中的一个线程异常了会被怎么处理?...相关推荐

  1. 【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计的话,如何实现一个线程池 文章目录 [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计 ...

  2. 进程中的一个线程死了所引发的后果

    我们知道,同一个进程中的多个线程共享进程资源,包括主内存.文件句柄.锁资源等.那么当一个线程死了(非正常退出.死循环等)就会导致线程该占有的资源永远无法释放,从而影响其他线程的正常工作,看下面一个例子 ...

  3. python线程暂停_在python中暂停一个线程和另一个线程

    我正在研究如何在python中执行多线程(2个线程).在 我要他们中的一个一直在读串行端口.读取每个帧并将其保存到数据库中.我已经做了一个脚本来做这个.在 对于第二个,我希望它监听一个套接字端口.当它 ...

  4. java 如何捕获线程中的异常处理_如何捕获Java中另一个线程抛出的异常?

    参见英文答案 > How to catch an Exception from a thread                                    14个 我正在使用一个创建 ...

  5. python 线程重启_在Python中重新启动一个线程

    我正在尝试为 Python 3.4中的项目制作线程飞行软件,其中我需要线程重新启动,以防在传感器读取期间发生I / O错误或其他类似的侥幸崩溃.因此,我正在制作一个看门狗来检查线程是否已经死亡并重新启 ...

  6. JAVA导出exls时报oom_如何实现导出百万条数据到EXCEL中不报OOM异常?

    Java项目中使用POI导出百万条数据到Excel中,但是会出现内存溢出异常. 存在以下问题需要考虑POI导出条数限制6w+ 数据量大的话会导致内存溢出 现在的做法是每6w条数据做一次分割,创建一个新 ...

  7. java 手编线程池_死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  8. 深读源码-java线程系列之自己手写一个线程池

    问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写的线程池如何测试? 简介 线程池是Java并发编程中经常使用到的技术,那么自己如何动手写一个线程池呢?本文将手把手带你写一个可用的线 ...

  9. java中等待所有线程都执行结束

    使用CountDownLatch,这其实是最优雅的写法了,每个线程完成后都去将计数器减一,最后完成时再来唤醒 @Test public void testThreadSync3() { final V ...

最新文章

  1. 图论数学:矩阵树定理
  2. OpenCASCADE:Modeling Data之几何实用程序
  3. matlab中给图像加几个矩形框_没想到!PPT中的这个效果,用好了,简直就是渣图美化器...
  4. Ubuntu linux 查看串口连接信息
  5. HIBERNATE与 MYBATIS的对比
  6. IP头,TCP头,UDP头,MAC帧头定义(转)
  7. unity 创建NGUI字体
  8. VS2010中的错误代码号及其含义
  9. VMD变分模态分解代码,C++代码下载
  10. 计算领域高质量科技期刊分级目录
  11. Ubuntu安装MDK5
  12. SMOTE算法代码实现
  13. java获取异常行数,如何增加Java堆栈跟踪转储的显示行数?
  14. Unity LOGO流光效果
  15. Matlab——数组
  16. 服务器系统事件id1001,WIN10事件查看器,ID1000,ID1001 問題
  17. 稽首文殊,寒山之士;南无普…
  18. 微信小程序前端合包流程weshop
  19. 微服务组件之限流器与熔断器
  20. Unity人物角色动画系统学习总结

热门文章

  1. Scala学习(二、控制结构)
  2. 数据分析数据挖掘(二)
  3. 当前仍在编辑文章 - Java 并 发 编 程 基 础
  4. java 位运算 hashcode_hashcode面试题
  5. AcWing 4242. 货币兑换(SPFA or Bellman 判正权环)
  6. 第二单元答案计算机基础,《计算机基础》资源包-第二单元课后题答案.docx
  7. linux连接wpa wifi密码,Linux环境下使用WIFI模块:使用wpa_supplicant工具配置和连接WIFI-Go语言中文社区...
  8. 地理住宅区的特点_高三地理复习专题讲解:民居特点与自然环境的关系
  9. 办公用品管理系统VB——模块
  10. ylbtech-LanguageSamples-Indexers_2(索引器)