ThreadPoolExcutor 线程池 异常处理 (上篇)
前言
最近看到crossoverJie的一篇文章:一个线程罢工的诡异事件
首先感谢原作者的分享,自己获益匪浅。然后是回想到自己的一次面试经历,面试官提问了线程池中的线程出现了异常该怎样捕获?会导致什么样的问题?
示例代码
public class ThreadPoolException {
    private final static Logger LOGGER = LoggerFactory.getLogger(ThreadPoolException.class);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService execute = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
        execute.execute(new Runnable() {
            @Override
            public void run() {
                LOGGER.info("=====11=======");
            }
        });
        TimeUnit.SECONDS.sleep(5);
        execute.execute(new Run1());
    }
    private static class Run1 implements Runnable {
        @Override
        public void run() {
            int count = 0;
            while (true) {
                count++;
                LOGGER.info("-------222-------------{}", count);
                if (count == 10) {
                    System.out.println(1 / 0);
                    try {
                    } catch (Exception e) {
                        LOGGER.error("Exception",e);
                    }
                }
                if (count == 20) {
                    LOGGER.info("count={}", count);
                    break;
                }
            }
        }
    }
}
上面的代码是原作者本地调试的一个代码,这里我也大致交代下情形:
- 首先是启动main方法看最终执行现象
  
这里直接抛异常了,by zero。看到底层是ThreadPoolExecutor 1149行抛出的。
查看线程dump,发现线程池中的线程此时处于WAITING状态

- 源码追踪
 这里就需要弄清楚为何会出现WAITING状态,所以我们需要一步步追踪源码。
 我们可以在抛异常的地方打断点,然后一步步跟踪:
  
在执行1149行代码由于抛了异常,所以继续执行finally中processWorkerExit方法:

processWorkerExit中主要做了两件事,worker remover和addWorker。线程池中的任务都会被包装为一个内部 Worker 对象执行。不清楚的可以参考:Java并发之线程池ThreadPoolExecutor源码学习

最后会执行addWorker,紧接着我们继续往addWorker中去跟,看看里面做了什么操作:

addWorker里面是重新new Worker(), 然后执行worker.start(), 接着我们看下Worker中的start方法:

因为Woker是实现Runnable接口的,所以会执行其run方法,接着往runWorker方法跟踪:

因为此时的Worker是上一步重新new出来的,所以其中的task为空,这时需要继续跟踪getTask()方法:

此时因为线程池的队列中并没有任务,所以这里执行take会一直阻塞,也就有了最开始的那个WAITING的状态了。
到了这里一切都很明了了,源码面前任何妖魔鬼怪都无法藏匿,所以但我们使用线程池的时候一定要注意一异常的捕获和处理。
下一章来详细解读一下如何捕获线程池中的异常。
由于本人水平有限,文章中如果有不严谨的地方还请提出来,愿闻其详。
ThreadPoolExcutor 线程池 异常处理 (上篇)的更多相关文章
- ThreadPoolExcutor 线程池 异常处理 (下篇)
		前言 因为这是之前面试的一个题目,所以印象比较深刻,前几天写了一篇文章:ThreadPoolExcutor 线程池 异常处理 (上篇) 中已经介绍了线程池异常的一些问题以及一步步分析了里面的一些源代码 ... 
- JDK线程池异常处理方式
		1. 抛出异常 execute() java.util.concurrent.ThreadPoolExecutor#runWorker 中抛出,抛出之后经过以下两个步骤: catch块捕获,捕获之后再 ... 
- JAVA 线程池之Callable返回结果
		本文介绍如何向线程池提交任务,并获得任务的执行结果.然后模拟 线程池中的线程在执行任务的过程中抛出异常时,该如何处理. 一,执行具体任务的线程类 要想 获得 线程的执行结果,需实现Callable接口 ... 
- 面试必备:Java线程池解析
		前言 掌握线程池是后端程序员的基本要求,相信大家求职面试过程中,几乎都会被问到有关于线程池的问题.我在网上搜集了几道经典的线程池面试题,并以此为切入点,谈谈我对线程池的理解.如果有哪里理解不正确,非常 ... 
- Java线程池面试
		New Thread的弊端 每次new Thread会新建对象,性能差 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或OOM 缺少更多功能,如更多执行.定期执行.线 ... 
- 美团动态线程池实践思路开源项目(DynamicTp),线程池源码解析及通知告警篇
		大家好,这篇文章我们来聊下动态线程池开源项目(DynamicTp)的通知告警模块.目前项目提供以下通知告警功能,每一个通知项都可以独立配置是否开启.告警阈值.告警间隔时间.平台等,具体代码请看core ... 
- JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理
		本文记录: 1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败. 2 ... 
- java 线程池第一篇 之 ThreadPoolExcutor
		一:什么是线程池? java 线程池是将大量的线程集中管理的类,包括对线程的创建,资源的管理,线程生命周期的管理.当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程.减少系统资源的 ... 
- 线程池:ThreadPoolExcutor源码阅读
		ThreadPoolExcutor源码流程图:(图片较大,下载再看比较方便) 线程池里的二进制奥秘 前言: 线程池的五种状态state(RUNNING.SHUTDOWN.STOP.TIDYING.TE ... 
随机推荐
- hdu 3001 Travelling (三进制)【状压dp】
			<题目链接> 题目大意: 给出n个点和m条边,求经过所有点所需的最小花费,每个点最多经过两次. 解题分析: TSP问题类型,由于此题每个点有三种状态,所以采用三进制状态压缩,0.1.2 分 ... 
- Python并发复习4- concurrent.futures模块(线程池和进程池)
			Python标准库为我们提供了threading(多线程模块)和multiprocessing(多进程模块).从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提 ... 
- css position相对定位与绝对定位彻底搞懂
			定位position position本身就有给...定位的意思 position属性的值: static ---默认值 relative ---相对定位 absolute ---绝对定位 fixed ... 
- springboot2 redis
			本项目使用jar包: <parent> <groupId>org.springframework.boot</groupId> <artifactId> ... 
- Alpha(5/10)
			鐵鍋燉腯鱻 项目:小鱼记账 团队成员 项目燃尽图 冲刺情况描述 站立式会议照片 各成员情况 团队成员 学号 姓名 git地址 博客地址 031602240 许郁杨 (组长) https://githu ... 
- C#Windows窗体界面设计_05_添加菜单栏 工具栏 状态栏 按钮
- Codeforces.468C.Hack it!(构造)
			题目链接 \(dls\)出的比赛诶...这么妙. \(Description\) 令\(f(x)\)表示整数\(x\)在十进制下各个数位的数字之和.给定\(a\),求两个整数\(l,r\),使得\(\ ... 
- emoji
			嗯...闲的... emoji:(博客园的markdown支持emoji编码...惊了) http://getemoji.com/ http://www.fhdq.net/emoji/emojifuh ... 
- 流畅的Python读书笔记(二)
			2.1 可变序列与不可变序列 可变序列 list. bytearray. array.array. collections.deque 和 memoryview. 不可变序列 tuple. str 和 ... 
- Stm32常见英文缩写
			Stm32常见英文缩写 https://wenku.baidu.com/view/4b9c2eee5022aaea998f0f5b.html STM32嵌入式开发常见缩写 https://wenku. ... 
