Executors:为什么阿里不待见我?
大家好,我是Excutors,一个老实的工具类。
有个叫老三的程序员在文章 要是以前有人这么讲线程池,我早就该明白了!里挖了一个坑,说要把我介绍给大家认识认识。
我其实挺委屈的,作为一个没得感情,老实干活的工具类,我却上了阿里巴巴的黑名单。他们在一本叫《Java开发手册》的册子里写道:

作者画外音:人家为啥给你拉黑,不写的清清楚楚嘛,你有啥可委屈的。而且你这个家伙就是表面看起来老实,活是你干的吗?干活的不都是小老弟ThreadPoolExecutor。来,我一个个给你数。
1. newFixedThreadPool
FixedThreadPool,是一个固定大小的线程池。
看一下它的源代码实现:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
直接调用ThreadPoolExecutor的构造方法。
核心线程数和最大线程数相同- 使用
LinkedBlockingQueue作为任务队列
FixedThreadPool的execute()运行示意图:

整体运行过程:
- 当前运行线程少于
corePoolSize,则创建新线程执行任务 - 当前运行线程大于
corePoolSize,将任务加入LinkedBlockingQueue - 线程池中线程执行完任务后,会循环从
LinkedBlockingQueue中获取任务执行
因为使用无界队列LinkedBlockingQueue来存储不能执行的任务,所以不会触发拒绝服务策略,可能会导致OOM。
2. newSingleThreadExecutor
SingleThreadExecutor是使用单个线程工作的线程池。
实现源码如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
直接调用ThreadPoolExecutor的构造方法。
核心线程数和最大线程数都是1- 使用
LinkedBlockingQueue作为任务队列
SingleThreadExecutor的运行流程:

- 当前无运行线程,创建一个线程来执行任务
- 当前有线程运行,将任务加入
LinkedBlockingQueue - 线程执行完任务后,会循环从
LinkedBlockingQueue中获取任务来执行
这里用了无界队列LinkedBlockingQueue,同样可能会导致OOM。
3. newCachedThreadPool
CachedThreadPool是一个会根据需要创建新线程的线程池。
实现源码:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
直接调用ThreadPoolExecutor的构造方法。
核心线程数为0,最大线程数是非常大的一个数字Integer.MAX_VALUE- 使用没有容量的
SynchronousQueue作为工作队列 keepAliveTime设置为60L,空闲线程空闲60秒之后就会被终止
CachedThreadPool的运行流程:

- 如果当前有空闲线程,使用空闲线程来执行任务
- 如果没有空闲线程,创建一个新线程来执行任务
- 新建的线程执行完任务后,会执行
poll(keepAliveTime,TimeUnit.NANOSECONDS),在SynchronousQueue里等待60s
这里线程池的大小没有限制,可能会无限创建线程,导致OOM。
4. newScheduledThreadPool
ScheduledThreadPool是一个具备调度功能的线程池。
实现源码:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
可以看到,这个线程池不太一样,它调用的是ScheduledThreadPoolExecutor的构造方法。
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
- 最大线程数是
Integer.MAX_VALUE,无限大 - 使用
DelayedWorkQueue作为任务队列
ScheduledThreadPoolExecutor执行任务的流程:

主要分为两大部分:
- 调用
scheduleAtFixedRate()/scheduleWithFixedDelay()方法,会向DelayQueue添加一个ScheduledFutureTask。 - 线程池的线程从
DelayQueue中获取ScheduledFutureTask,然后执行任务。
它同样可以无限创建线程,所以也存在OOM的风险。
为了实现周期性执行任务,ScheduledThreadPoolExecutor对ThreadPoolExecutor进行了一些改造[4]:
ScheduledFutureTask来作为调度任务的实现它主要包含了3个成员变量
time(任务将要被执行的具体时间)、sequenceNumber(任务的序号)、period(任务执行的间隔周期)使用
DelayQueue作为任务队列DelayQueue封装了了一个PriorityQueue,会对对队列中的ScheduledFutureTask进行排序,排序的优先级time>sequenceNumber。

ScheduledThreadPoolExecutor的任务执行主要分为4步:
- 线程池里的
线程1从DelayQueue中获取已到期的ScheduledFutureTask(DelayQueue.take()) 线程1执行这个ScheduledFutureTask线程1修改ScheduledFutureTask的time变量为下次将要被执行的时间。线程1把这个修改time之后的ScheduledFutureTask放回DelayQueue中(DelayQueue.add())
Excutors自述:这,这……工具类出的问题不叫bug。虽然我偷懒不干活,还可能会OOM,但我还是一个好工具类,呜呜……
作者:是啊,其实Excutors有什么错呢?它只是一个没得感情的工具类,有错的只是不恰当地用它的人。所以,知其然且知其所以然,搞懂原理,灵活应用。我们应该像一个士兵一样,不只是会扣动扳机,还会拆解保养枪械。
我是三分恶,一个号称能文能武的全栈开发。
点赞、关注不迷路,咱们下期见!
参考:
[1]. 《Java并发编程的艺术》
[2]. 讲真 这次绝对让你轻松学习线程池
[3]. 小傅哥 《Java面经手册》
[4]. 《Java并发编程之美》
[5]. 阿里巴巴《Java开发手册》
Executors:为什么阿里不待见我?的更多相关文章
- 附001.Docker阿里云Registry加速器配置
一 安装配置docker 1.1 安装docker 见<002.docker版本及安装>. 1.2 配置国内阿里云加速器 见<002.docker版本及安装>. 二 配置阿里云 ...
- J.U.C体系进阶(一):juc-executors 执行器框架
Java - J.U.C体系进阶 作者:Kerwin 邮箱:806857264@qq.com 说到做到,就是我的忍道! 主要内容: juc-executors 执行器框架 juc-locks 锁框架 ...
- java线程池,阿里为什么不允许使用Executors?
带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...
- 阿里不允许使用 Executors 创建线程池!那怎么使用,怎么监控?
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 五常大米好吃! 哈哈哈,是不你总买五常大米,其实五常和榆树是挨着的,榆树大米也好吃, ...
- 阿里技术专家十五问,真题面试刀刀见肉,快来和阿里面试官battle
引言 2020阿里巴巴专家组出题,等你来答: 题目:如何判断两个链表是否相交 出题人:阿里巴巴新零售技术质量部 参考答案: $O(n^2)$: 两层遍历,总能发现是否相交 $O(n)$: 一层遍历,遍 ...
- 阿里Java开发手冊之编程规约
对于程序猿来说,编程规范能够养成良好的编程习惯,提高代码质量,减少沟通成本.就在2月9号,阿里出了一份Java开发手冊(正式版),分为编程规约.异常日志.MySQL规约,project规约.安全规约五 ...
- 我的阿里之路+Java面经考点
我的阿里之路+Java面经考点 时间:2018-03-19 23:03 来源:未知 作者:admin 点击:87次 我的2017是忙碌的一年,从年初备战实习春招,年三十都在死磕JDK源码,三 ...
- [源码阅读] 阿里SOFA服务注册中心MetaServer(2)
[源码阅读] 阿里SOFA服务注册中心MetaServer(2) 目录 [源码阅读] 阿里SOFA服务注册中心MetaServer(2) 0x00 摘要 0x01 MetaServer 注册 1.1 ...
- JUC知识点总结(知识点见内部目录)
目录 JUC是什么 锁 Synchronized VS Lock 实现差异 Synchronized & Lock 总结 Synchronized锁的对象是什么 生产者&消费者 只有两 ...
随机推荐
- python学习笔记(四)-文件操作
文件读写"""一.文件打开有3种方式 1.读 r #如果打开的文件的时候没有指定模式,那么默认是读 读写模式 r+,只要沾上r,文件不存在的时候,打开都会报错 2.写 w ...
- Viterbi 算法 Python实现 [NLP学习一]
最近思考了一下未来,结合老师的意见,还是决定挑一个方向开始研究了,虽然个人更喜欢鼓捣.深思熟虑后,结合自己的兴趣点,选择了NLP方向,感觉比纯粹的人工智能.大数据之类的方向有趣多了,个人还是不适合纯粹 ...
- P7408-[JOI 2021 Final]ダンジョン 3【贪心,树状数组】
正题 题目链接:https://www.luogu.com.cn/problem/P7408 题目大意 一个有\(n+1\)层的地牢,从\(i\)到\(i+1\)层要\(A_i\)点能量,第\(i\) ...
- disruptor笔记之五:事件消费实战
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- WPF进阶技巧和实战03-控件(5-列表、树、网格03)
数据视图 数据视图是在后台工作的,用于协调绑定数据的集合.使用数据视图可以添加导航逻辑.实现数据过滤.排序.分组. 当将集合或者DataTable绑定到ItemsControl控件时,会不加通告地在后 ...
- JVM类加载器的分类
类加载器的分类 JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader). 从概念上来讲,自定 ...
- nodejs安装 及环境变量配置教程 超详细版
------------恢复内容开始------------ ------------恢复内容开始------------ 上篇文件 写到 遇到了两个棘手问题 : @终端进程启动失败: shell ...
- Linux下关于用户账户的几个文件解析
Linux下关于用户账户的几个文件解析 Linux是一个多用户系统,但是对于一个多用户共存的系统中,当然不能够出现用户相互越权等一系列的安全问题,所以如何正确的管理账户成为了Linux系统中至关重要的 ...
- 洛谷luogu3957跳房子(单调队列优化)
QwQ被普及组的题折磨的死去活来. 硬是卡线段树,没卡过QwQ oi生涯,第一道正经的单调队列dp题 进入正题 题目大意: 其中\(n \le 500000\) 看到这个题的第一感觉就是二分金币数 很 ...
- 【原创】C语言和C++常见误区(一)
本文仅在博客园发布,认准原文地址:https://www.cnblogs.com/jisuanjizhishizatan/p/15414469.html 问题1:int类型占几个字节? 常见误区:占4 ...