Executors功能如此强大,ThreadPoolExecutor功不可没(一)

Android线程池全面解析:Executors工厂方法与阿里规约的深层思考 文章摘要: Android开发中合理使用线程池对应用性能至关重要。Executors提供的四种线程池(FixedThreadPool、CachedThreadPool、SingleThreadExecutor和ScheduledThreadPool)各有特点,但都暗藏风险:无界队列可能导致OOM,无限创建线程会耗尽资源。阿里Java规约建议手动创建线程池,通过控制核心参数(线程数、队列容量、拒绝策略)规避风险。最佳实践包括:使用有界队列、限制最大线程数、自定义线程工厂、选择合适的拒绝策略(如CallerRu 阅读详情

作为 Java 程序员,无论是技术面试、项目研发或者是学习框架源码,不彻底掌握 Java 多线程的知识,做不到心中有数,干啥都没底气,尤其是技术深究时往往略显发憷。

在 JDK1.5 以前,研发人员在面对线程频繁调度的场景,必须手动打造线程池,来节约系统开销(画外音:真是吃了不少苦头)。

从 JDK1.5 开始,Java 提供了一个 Excutors 工厂类来生产线程池,可以帮助研发人员有效的进行线程控制(画外音:不用造轮子啦,爽歪歪)。

(配图释义:JDK 1.8 能用 Excutors 创建的线程池)

如上图示意,Excutors 提供了满足各种场景的线程池创建方式, Java 研发人员就不用苦逼哈哈的去造轮子啦,谁用谁爽。

但是,阿里开发规约明确强制研发人员:线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式。

(配图释义:阿里巴巴Java开发手册,线程池创建规约)

不过,若经常关注源码的同学会发现,无论是 newFixedThreadPool() 方法、newSingleThreadExecutor() 方法,还是 newCachedThreadPool() 方法,其背后均使用了 ThreadPoolExecutor。

(配图释义:JDK 1.8 能用 Excutors 创建的线程池的背后)

通过上面源码截图,可以清晰看出,以上几种创建线程池的方式,均是对 ThreadPoolExecutor 类的封装,所以要想彻底掌握线程池,势必要吃透线程池背后的 ThreadPoolExecutor。

1

 解剖:构造函数  

有关 ThreadPoolExecute 构造函数,很多书上或者文章都会提到,下面再简单了解一下每个参数的具体含义。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

构造函数的参数释义:

corePoolSize:指定线程池中的线程数量; 

maximumPoolSize:指定线程池中的最大线程数量;

keepAliveTime:当线程池中线程数量超过 corePoolSize 时,空闲线程的存活时间; 

unit:keepAliveTime 的单位; 

workQueue:任务队列,存放提交尚未被执行的任务; 

threadFactory:线程工厂,用于创建线程,一般用默认的即可;

handler:拒绝策略,当任务太多来不及处理,如何拒绝任务。

以上参数除了 workQueue 以及 handler 外,大部分都很易懂。接下来重点说说 workQueue 以及 handler 两个参数。

参数 BlockingQueue<Runnable> workQueue,是用于存放提交尚未被执行的任务的队列,类型是 BlockingQueue 接口的对象,用于存放 Runnable 对象。

参数 RejectedExecutionHandler handler 是指当任务数量超过系统承载能力时,该如何处理?其中 JDK 提供了四种拒绝策略。

(配图释义:JDK 1.8 内置的拒绝策略)

JDK 提供的四种拒绝策略归纳,简单了解一下。

2

 思考:使用 Executors 会导致 OOM?  

了解完 ThreadPoolExecutor 类的构造函数,接下来探讨一下阿里开发手册明确强制的一条使用线程池的规约。

为了更清晰的认识,不妨走进源码看一看。首先走进 newFixedThreadPool() 方法的源码,一探究竟。

如源码截图所示,newFixedThreadPool() 方法的实现,返回一个 corePoolSize 和 maximumPoolSize 大小一样的,并且使用了 LinkedBlockingQueue 任务队列的线程池。

如上面 LinkedBlockingQueue 的源码所示,队列的默认长度为 Integer.MAX_VALUE,那么当任务提交频繁时,线程池中的线程处理不过来时,队列可能会迅速膨胀,从而会出现 OOM。

接着走进 newSingleThreadExecutor() 方法的源码,看看有没有新大陆。

如源码截图示意,newSingleThreadExecutor 方法实现中,corePoolSize 和 maximumPoolSize 设置的值均为 1,返回一个单线程的线程池,并且使用 LinkedBlockingQueue 任务队列来存在提交的任务,与 newFixedThreadPool() 方法一样,当任务提交频繁时,线程池中的线程处理不过来时,队列会迅速膨胀,从而会出现 OOM。

最后看看 newCachedThreadPool() 方法的源码实现,一探究竟。

如上图源码示意,newCachedThreadPool() 方法实现,返回了一个 corePoolSize 为 0,maximumPoolSize 的值为 Integer.MAX_VALUE,并且使用 SynchronousQueue 作为任务队列的线程池。

而 SynchronousQueue 队列是一种直接提交的队列(不会保存提交的任务),所以总会使线程池增加新的线程来执行任务,当任务执行完毕后,由于 corePoolSize 为 0,因此空闲线程又会在 60 秒内被回收。

如果同时有大量任务被提交,而任务的执行又不那么快时,newCachedThreadPool() 方法,便会开启大量的线程进行处理,这样可能很快耗尽系统的资源,进而导致 OOM。

3

寄语写最后 

本次,主要引入线程池背后的 ThreadPoolExecutor 类,算是正式开启探寻线程池背后的奥秘之旅,先有个初步的认识,知其然知其所以然,后续会逐步深入。

好了,本次就谈到这里,一起聊技术、谈业务、喷架构,少走弯路,不踩大坑。会持续输出原创精彩分享,敬请期待!

推荐阅读:

彻底搞懂 Java 线程池,干啥都不再发憷

Java程序跑的快,全要靠线程带

fastjson的这些坑,你误入了没?

真实|技术人员该如何站好最后一班岗?

Java 8 的这些特性,你知道吗?

改掉这些坏习惯,还怕写不出健壮的代码?(一)

改掉这些坏习惯,还怕写不出优雅的代码?(二)

改掉这些坏习惯,还怕写不出优雅的代码?(三)

改掉这些坏习惯,还怕写不出健壮的代码?(四)

改掉这些坏习惯,还怕写不出精简的代码?(五)

改掉这些坏习惯,还怕写不出精简的代码?(六)

坚持是一种信仰,在看是一种态度!

Deepseek 10分钟化身理性荐股神器:触碰程序员不敢想的天花板 在这个消息疯狂、波动频繁的市场,“理性”两字显得弥足珍贵。通过Deepseek+AkShare+Aktools+Dify四位一体的方案,能帮我们降低信息搜集成本,并在短期投资领域搭建出一套“可解释、低门槛、易定制”的量化荐股流程。不要再盲目听小道消息或依赖情绪驱动,不妨给自己一个机会,让数据说话。而要注意的是,“理性荐股”并非万能,它只是工具,最终的收益还得依赖投资者自身对风险和机遇的权衡。祝大家都能在这股市里收获理性的底气,寻得更精准的入场时机。 阅读详情

相关推荐

基于强化学习框架的交易策略学习过程

每个状态s∈S 是一个由六个微观结构特征构成的向量,这些特征反映了当前市场的订单簿状态和近期交易行为。

xu624735206的博客 1110

Java线程(五):Executors、ThreadFactory

Executors public class Executors 一个功能非常强大的辅助类。 此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。 此类支持以下各种方法: 创建并返回设置有常用配置字符串的 ExecutorService 的方法。 创建并返回设置有

SayNight 6916

Dify工作流构建案例:迭代驱动的多维深度搜索

为了克服这些挑战,我们可以设计一个能够智能协同内部知识库与外部互联网搜索,并最终由大型语言模型(LLM)进行深度整合与精准回答的高级工作流。

同名公众号:dify实验室 2291

Java Executor并发框架(三)ThreadFactory介绍

一、介绍 使用 ThreadFactory 创建新线程。如果没有另外说明,则在同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态等等。如果从 new

pfnie的博客 2018

跨境电商ERP开发之Shopee开发者账号申请

引言:由于电子信息技术和经济全球化的进一步发展,电子商务在国际贸易中的影响力和关键作用日渐突显,已变成中国出口贸易的市场趋势。跨境电商未来的发展前景必定是有助于减少经济成本、推动全球贸易便利化,有助于提高国内群众福祉,有助于打造良好的营商环境,从而推动经济长期健康发展。 gitee仓库地址: https://gitee.com/naturalwish/SSERP/tree/master 以下授权教学同ShopeeOpen Platform - Developer Guide 申请流程 ..

naturalwish的专栏 3637

伯德图详解:从传递函数到系统稳定性的频域分析

在自动控制与控制系统设计中,理解系统对不同频率输入信号的响应特性,是分析和设计稳定系统的核心基础。频率响应描述了系统对正弦输入的幅值增益与相位变化规律,而伯德图作为最直观的频域分析工具,通过对数坐标将宽频带特性压缩成一条清晰曲线,让工程师无需复杂计算即可快速评估系统性能。从典型环节的渐近线绘制,到相位裕度、幅值裕度的读取,伯德图贯穿了系统稳定性判断、控制器参数整定及噪声抑制等关键场景。本文结合实际调试经验,系统讲解伯德图的绘制原理与读图方法,帮助读者快速掌握从传递函数到工程应用的核心技能。

weixin_34535286的博客 336

Executors线程池详解(全)

开场白 构造一个线程池为什么需要几个参数?如果避免线程池出现OOM?Runnable和Callable的区别是什么?本文将对这些问题一一解答,同时还将给出使用线程池的常见场景和代码片段。 基础知识 Executors创建线程池 Java中创建线程池很简单,只需要调用Executors中相应的便捷方法即可,比如Executors.newFixedThreadPool(int nThreads...

qq_33642970的博客 2306

架构决策之消息中间件MQ系列六-Pulsar

一、架构

恰恰虎的博客 7253

【Thread】线程池的 7 种创建方式及自定义线程池

1. 什么是线程池 线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制。它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。 使用线程池主要有以下优点: 降低资源消耗 提高响应速度 提高线程的可管理性 同时,阿里巴巴在其《Java开发手册》中也强制规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 2. 使用线程池 线程池的创建方法总共有 7 种,但总体来说可分为 2 类:

sco5282的博客 3万+

宽压 DC⇌DC 也能“随心所欲”——全桥 LLC 混合控制硬核拆解

硬件派 vs. 软件派:多电平是“器件堆砌”,混合控制是“算法魔改”。预算紧 → 先搞软件。仿真别嫌烦:PLECS 把两条曲线扫透,切换点、死区、φ 都调到波形平滑再上板。温升留 20 ℃ 余量:车规≥125 ℃,实验室测 105 ℃ 就算危险,别玩极限。

weixin_43199439的博客 926

《四》:LBE,VR 大空间系列——Pico的空间扫描方式

(这里有个选项叫高精度扫描模式,这个功能在下方详细补充)系统会根据绘制的顶点,将区域分割成若干个4X4米的小方格,我们只需要根据提示,首先进入一个方格子空间内部,然后依次凝视每个区域上下左右前后六个面的小方格组,每一面4个,直至全部消失, 消失后地面会出现一个方形行走路径,我们沿着边缘正或反走一圈即可,完成后此块区域即自动消失。不过由于pico有一个高精度扫描圈,如图加粗的圆环,这个圆环的意思是在在内部的区域扫描精度较高,越远离原点的区域误差越大,所以为了更有效的利用,建议原点设置在场地中心区域。

unitygroup的博客 2882

线程池原理(六):Executors

Executors是线程池的工厂类,可以创建ExecutorService、ScheduledExecutorService、ThreadFactory、Callable的实例。

千磨万击还坚韧,任尔东西南北风 1375

架构师之HBase vs MongoDB 技术选型与场景决策实战案例

面对海量数据和高并发查询,该选 HBase 还是 MongoDB?本文为你提供完整的决策框架!从数据模型对比、架构解析、六大真实场景(电信 CDR、金融行情、广告点击流、电商商品、社交档案、内容管理)到性能、一致性、运维全面对比,助你在 PB 级时序数据和灵活查询之间做出精准选择!

肖哥弹架构博客 1100

【Java 并发编程】Java 创建线程池的正确姿势: Executors 和 ThreadPoolExecutor 详解...

这种情况下,一旦提交的线程数超过当前可用线程数时,就会抛出java.util.concurrent.RejectedExecutionException,这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。其实,在上面的报错信息中,我们是可以看出蛛丝马迹的,在以上的代码中其实已经说了,真正的导致OOM的其实是LinkedBlockingQueue.offer方法。Executors的创建线程池的方法,创建出来的线程池都实现了ExecutorService接口。

AI天才研究院 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java.util.concurrent.Executor、ExecutorService、ThreadPoolExecutor、Executors,ThreadFactory

一、java.util.concurrent.Executor 一个对象执行提交 Runnable任务; Executor通常不是显式创建线程; /** * Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion o...

ScorpC的博客 724

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明

ScheduledThreadPoolExecutor 及 ThreadPoolExecutor

fumeidonga的博客 2386

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java:ThreadPoolExecutor解析续--Executors

简介 Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务的线程相当于消费者,并用Runnable来表示任务,Executor的实现还提供了对生命周期的支持,以及统计信息收集,应用程序管理机制和性能监视等机制。 Executors:提供了一系列静态...

demon7552003的小本本 197

【Java面试进阶】谈谈为什么禁止使用Executors创建线程池?

谈谈为什么禁止使用Executors创建线程池?什么是Executors?Executors存在什么问题?Executors为什么存在缺陷?如何正确创建线程池? 首先,可以通过Executors静态工厂构建线程池,但是一般不建议这样使用。 什么是Executors? Executors是一个Java中的工具类。提供工厂方法来创建不同类型的线程池。如下所示: 从源码中可知,Executors的创建线程池的方法,创建出来的线程池都实现了ExecutorService接口。常用方法有以下几个: newFixe

小哲的博客 5899

线程池-Executors

  在实际项目中,大家或多或少都会遇到多线程设计问题。这是为什么呢?为了尽可能提高系统的吞吐量和性能。创建和使用线程非常简单,这也就导致很多项目在各种任务中频繁的创建线程,虽然与进程相比,线程是一种轻量级工具,但是创建和销毁都需要花费时间,太过于频繁,也会耗尽CPU和内存资源。 大量的使用线程,如果导致系统出现OOM,这就违反我们的初衷了。使用线程,我们要有一个度,真实环境中,应该对线程加以控...

二月初二 1237

Java线程池深度解析:从Executors工厂到ThreadPoolExecutor核心参数与生产实践

在并发编程中,线程池是一种管理和复用线程资源的经典设计模式,其核心原理是通过预先创建一组线程并维护一个任务队列,来避免频繁创建和销毁线程带来的性能开销。这种技术能显著提升系统吞吐量、降低资源消耗,并增强应用的稳定性。从技术价值看,线程池实现了任务提交与执行的解耦,让开发者能更专注于业务逻辑,同时提供了流量削峰、资源隔离等工程实践能力。在Java生态中,`java.util.concurrent`包下的`ThreadPoolExecutor`是实现线程池的基石,而`Executors`工厂类则提供了快速创建常

weixin_32612263的博客 371

Java中的工具类Executors详解

如果没有可用的线程,则创建一个新线程并添加到池中。从上图中也可以看出,Executors的创建线程池的方法,创建出来的线程池都实现了ExecutorService接口。就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,这种情况下就有可能因为任务过多而导致内存溢出问题。其实,在上面的报错信息中,我们是可以看出蛛丝马迹的,在以上的代码中其实已经说了,真正的导致OOM的其实是。是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为。

白话机器学习 891

java中Executors创建线程池的三种方法

三个关键线程池的比较 1、创建单个线程(单例模式) public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, ...

jjj___jjj的博客 3万+

Java多线程(六):线程池详解_executors

线程池(ThreadPool)是⼀种基于池化思想管理和使用线程的机制。它是将多个线程预先存储在⼀个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。

2501_90405047的博客 699

15 Executor框架,ThreadPoolExecutor、FixedThreadPool,SingleThreadExecutor,CachedThreadPool,Executors工具类

Executor框架、ExecutorService、Executors FixedThreadPool 可重用固定线程数的线程池 SingleThreadExecutor 单线程线程池 CachedThreadPool 可调整线程数的线程池 Executor框架的执行流程 Executor框架的成员 ThreadPoolExecutor、ScheduledThreadPoolExecutor、 Future接口、Runnable接口、Callable接口和Executors

思念十年后 253

Java基础:ThreadPoolExecutor线程池学习

参考:https://blog.youkuaiyun.com/wtopps/article/details/80682267 前言 在互联网的开发场景下,很多时候需要我们用到多线程解决问题。从 Java 5 开始,Java 提供了自己的线程池,线程池就是一个线程的容器,每次只执行额定数量的线程。java.util.concurrent包中提供了ThreadPoolExecutor类来管理线程,本文将介绍一...

Gongyl的博客 400

深入浅出理解ThreadPoolExecutor

在互联网的开发场景下,很多业务场景下我们需要使用到多线程的技术,从 Java 5 开始,JDK中 提供了线程池的实现,线程池就是一个线程的容器,每次只执行额定数量的线程。java.util.concurrent包中提供了线程池类ThreadPoolExecutor类来管理线程,同时提供了工厂类Executors简化线程池的使用。本篇,我们将来详细的理解一下ThreadPoolExecutor的使用方式及其内部核心实现机制,让你明明白白的使用好线程池,Let’s do it!

wtopps的专栏 436
上一篇: 彻底搞懂 Java 线程池,干啥都不再发憷
下一篇: Java线程池深度揭秘
一猿小讲
博客等级 码龄15年 294粉丝 156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值