线程池中的线程如果发生异常,线程池是怎么处理的

结论
当一个线程池里面的线程异常后:


1、当执行方式是execute时,可以看到堆栈异常的输出
原因:ThreadPoolExecutor.runWorker()方法中,task.run(),即执行我们的方法,如果异常的话会throw x;所以可以看到异常。


2、当执行方式是submit时,堆栈异常没有输出。但是调用Future.get()方法时,可以捕获到异常
原因:ThreadPoolExecutor.runWorker()方法中,task.run(),其实还会继续执行FutureTask.run()方法,再在此方法中c.call()调用我们的方法,
如果报错是setException(),并没有抛出异常。当我们去get()时,会将异常抛出。


3、不会影响线程池里面其他线程的正常执行

4、线程池会把这个线程移除掉,并创建一个新的线程放到线程池中
当线程异常,会调用ThreadPoolExecutor.runWorker()方法最后面的finally中的processWorkerExit(),会将此线程remove,并重新addworker()一个线程。

源码执行流程

execute源码执行流程
1、开始执行任务,新增或者获取一个线程去执行任务(比如刚开始是新增coreThread去执行任务)。执行到task.run()时会去执行提交的任务。
      如果任务执行失败,或throw x抛出异常。
2、之后会到finally中的afterExecute()扩展方法,我们可以扩展该方法对异常做些什么。
3、之后因为线程执行异常会跳出runWorker的外层循环,进入到processWorkerExit()方法,此方法会将执行任务失败的线程删除,并新增一个线程。
4、之后会到ThreadGroup#uncaughtException方法,进行异常处理。
     如果没有通过setUncaughtExceptionHandler()方法设置默认的UncaughtExceptionHandler,就会在uncaughtException()方法中打印出异常信息。


submit源码执行流程
1、将传进来的任务封装成FutureTask,同样走execute的方法调用,然后直接返回FutureTask。
2、开始执行任务,新增或者获取一个线程去执行任务(比如刚开始是新增coreThread去执行任务)。
3、执行到task.run()时,因为是FutureTask,所以会去调用FutureTask.run()。
4、在FutureTask.run()中,c.call()执行提交的任务。如果抛出异常,并不会throw x,而是setException()保存异常。
5、当我们阻塞获取submit()方法结果时get(),才会将异常信息抛出。当然因为runWorker()没有抛出异常,所以并不会删除线程。
————————————————
版权声明:本文为CSDN博主「LiZhen798」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LiZhen314/article/details/119609565

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值