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 ...
随机推荐
- [译] Go数据结构-接口
原文 Go Data Structures: Interfaces 作者 Russ Cox 声明:本文目的仅仅作为个人mark,所以在翻译的过程中参杂了自己的思想甚至改变了部分内容.但由于译者水平有限 ...
- Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)
勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 本文导图: 一.由一个提问引发的思考 在Stack Overflow 看到这样一个问题 ...
- Django 学习第十天——状态保持及表单
状态保持: 1.http协议是无状态的:每次请求都是一次新的请求,不会记得之前通信的状态 2.客户端与服务器端的一次通信,就是一次会话实现状态保持的方式:在客户端或服务器端存储与会话有关的数据 3.存 ...
- java date HHmmss hhmmss
系统交互时,用到时间流水号的设计,出现时间流水号相同的情况,故对时间格式化各种情况做了研究 SimpleDateFormat(format) format:年月日 yyyyMMdd时分秒 HHmm ...
- MySQL 安装包下载教程
http://www.mysql.com/downloads/
- Jmeter测试http+JSON配置相关
1.添加HTTP信息头管理器 Content-Type application/json Accept application/json 2.添加http请求(方法.编码.路径.body)
- Codeforces.1096E.The Top Scorer(组合)
题目链接 感觉这题很裸啊,除了看着恶心点也没什么了,怎么过的人那么少.. \(Description\) 给定\(n,r,s\),表示有\(n\)个人,设每个人的得分是非负整数\(a_i\),已知第一 ...
- SpringIOC和DI
1.Spring的概念 Spring的绿草丛(一) Spring轻量级框架, Java EE的春天,当前主流框架目标使现有技术更加易用,推进编码最佳实践内容IoC容器AOP实现数据访问支持简化JDBC ...
- [APIO2012]派遣
[APIO2012]派遣 题目大意: 给定一棵\(n(n\le10^5)\)个结点的有根树,每个点有代价\(c_i\)和权值\(l_i\),要求你选定一个结点\(k\),并在对应的子树中选取一个点集\ ...
- React使用DVA本地state传值取值
React使用DVA本地state传值取值 最近在用Ant Pro 做一个后台系统,在使用中发现Antd Pro使用DVA来实现redux+sagas+router一系列的功能,比传统方式要方便快捷的 ...