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锁的对象是什么 生产者&消费者 只有两 ...
随机推荐
- three.js 模型拖动之DragControls控制器
需求: 拖动场景内的模型 方案: 增加控制器DragControls 1.引入控制器 import { OrbitControls } from "three/examples/jsm/co ...
- div 可编辑--获取光标位置插入元素
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Language" ...
- Flask SSTI利用方式的探索
Flask SSTI利用方式的探索 一.SSTI简介&环境搭建 一个统一风格的站点,其大多数页面样式都是一致的,只是每个页面显示的内容各不相同.要是所有的逻辑都放在前端进行,无疑会影响响应 ...
- mysql数据备份及恢复详细操作
一.数据库数据备份 1.全备 BakDir=/backup/full #创建全备目录 LogFile=/backup/full/bak.log #创建备份日志 Date=`date +%Y%m%d` ...
- 深入思考软件工程,开启 DevOps 之旅
20 世纪 60 年代,软件开始脱离硬件,逐渐成为一个独立产业.至今,软件开发过程从瀑布模型.CMM/CMMI,到 20 年前敏捷的诞生,再到今天 DevOps 的火热,一代代软件人在思考和探索,如何 ...
- nGrinder 参数使用
背景: 性能测试中为了更加接近真实模拟现实应用,对于提交的信息每次都需要提交不同的数据,或使用不同的值,最为典型的就是登录时的账号. 性能测试工具需要提供动态参数化功能,如商业化的LoadRunner ...
- 2021年1月-第02阶段-前端基础-HTML+CSS进阶-VS Code 软件
软件安装 VSCode软件 能够安装 VS Code 能够熟练使用 VS Code 软件 能够安装 VS Code 最常用的插件 1. VS Code简介 1.1 VS Code 简介 Visual ...
- 分布式事物SAGA
目录 概述SAGA SAGA的执行方式 存在的问题 重试机制 SAGA VS TCC 实现SAGA的框架 概述SAGA SAGA是1987 Hector & Kenneth 发表的论文,主要是 ...
- vue.$nextTick实现原理
源码: const callbacks = [] let pending = false function flushCallbacks () { pending = false const copi ...
- 【UE4】基础概念——文件结构、类型、反射、编译、接口、垃圾回收、序列化
新标签打开或者下载看大图 思维导图 Engine Structure Pipeline Programming Pipeline Blueprint Pipeline