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锁的对象是什么 生产者&消费者 只有两 ...
随机推荐
- k8s-PodApi对象
init容器 pod的生命周期钩子 资源限制 podApi对象概览 apiVersion + kind 一个是版本 一个是资源组 共同确定当前yaml由谁来管理 metadata元数据 用来唯一标 ...
- CF891C-Envy【可撤销并查集】
正题 题目链接:https://www.luogu.com.cn/problem/CF891C 题目大意 \(n\)个点\(m\)条边的一张无向联通图,每次询问一个边集能否同时出现在同一棵最小生成树上 ...
- Java——this关键字总结
一.this关键字的使用 1.当同类型的对象a和b,调用相同的方法method()时,为了区分该方法是被a调用还是被b调用 如下代码中,: class Banana { void method(int ...
- .Net微服务实战之可观测性
系列文章 .Net微服务实战之技术选型篇 .Net微服务实战之技术架构分层篇 .Net微服务实战之DevOps篇 .Net微服务实战之负载均衡(上) .Net微服务实战之CI/CD .Net微服务实战 ...
- mysql8 主从搭建
主:192.168.10.2 从:192.168.10.3 主:1.登录mysql,授权账号,让从数据库可以进行复制. mysql CREATE USER 'repl'@'192.168.10.3' ...
- 用OpenCV显示视频时遇到问题
刚刚接触OpenCV,运行了书上的例程,程序编译没有问题,在视频显示快要结束时遇到了下面的问题,代码在后面 #include "stdafx.h"#include <open ...
- 从零入门 Serverless | Serverless Kubernetes 应用部署及扩缩容
作者 | 邓青琳(轻零) 阿里云技术专家 导读:本文分为三个部分,首先给大家演示 Serverless Kubernetes 集群的创建和业务应用的部署,其次介绍 Serverless Kuberne ...
- AT3950 [AGC022E] Median Replace
题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,里面有一些还没有确定,我们标记为 ? .可以进行若干次操作,每次操作可以把三个相邻的数替换成它们的中位数.问有多少种 ...
- 单机CentOS 安装 TiDB
目录 一.官网教程 二.安装步骤 1.下载并安装 TiUP: 2.声明一下环境变量,否则会找不到 tiup 命令 3.安装 TiUP 的 cluster 组件: 4.官方教程说,由于模拟多机部署,需要 ...
- 面试题系列:new String("abc")创建了几个对象
new String("abc")创建了几个对象 面试官考察点猜想 这种问题,考察你对JVM的理解程度.涉及到常量池.对象内存分配等问题. 涉及背景知识详解 在分析这个问题之前,我 ...