一、写在前面

参考阿里开发规约,创建线程池一般用ThreadPoolExecutor

在高并发程序中,频繁创建与销毁线程是一种极其低效且不可控的行为。为了解决这个问题,Java 提供了线程池(ThreadPoolExecutor)这一强大的并发框架。它不仅提高了任务处理的效率,也帮助我们更好地控制系统资源,是现代高性能服务架构中的基石。

本文将从线程池的概念、设计目的、核心实现机制、任务调度流程、Worker 管理机制等方面入手


1.1 线程池是什么

线程池是一种线程复用机制,它维护了一组可以重复使用的工作线程,任务到来时无需创建新线程,而是复用已有线程执行任务,任务执行完毕后线程不会被销毁,而是回到池中待命。

Java 中的核心实现是 java.util.concurrent.ThreadPoolExecutor


1.2 线程池解决了什么问题

问题线程池的解决方案
线程创建销毁开销大线程复用,避免频繁构造/销毁
系统资源不可控线程数量上限可设,避免 OOM
并发请求过多无法及时处理使用阻塞队列缓存任务,异步处理
调度和控制困难提供任务调度、拒绝策略、监控接口
缺乏任务管理能力可统一提交、执行、取消任务


二、线程池核心设计与实现

2.1 总体设计架构

Java 线程池主要由以下组件构成:

┌──────────────┐     submit(Runnable)
│  主线程调用  ├────────────────┐
└──────────────┘                ▼┌──────────────┐│任务提交 execute│└─────┬────────┘▼┌────────────┐    (1)创建核心线程执行任务│ WorkerSet  │ ←────────────────────────┐└────┬───────┘                          │▼                                  │┌────────────────┐                          ││ BlockingQueue  │ ←───────(2)入队等待执行 │└──────┬─────────┘                          │▼                                    │(3)队列满,扩容线程池                  (4)满了,执行拒绝策略▼                                    ▼┌────────────────┐                    ┌────────────────┐│ maximumPoolSize│                    │ rejectHandler()│└────────────────┘                    └────────────────┘


2.2 生命周期管理

线程池有五种状态,由高位表示,低位为线程数量(workerCount),统一由 ctl 原子变量管理。

状态描述
RUNNING接收新任务,处理队列
SHUTDOWN拒收新任务,继续处理队列
STOP拒收新任务,中断执行线程
TIDYING所有任务执行完,清理中
TERMINATED清理完成,彻底关闭

生命周期状态在任务提交、线程退出、关闭线程池等场景中都会动态变化。


2.3 任务执行机制

2.3.1 任务调度流程(execute)

executor.execute(task) 时的完整流程:

  1. 线程池运行状态检查,若不是 RUNNING,直接拒绝任务。

  2. 线程数 < corePoolSize:创建新线程执行任务。

  3. 线程数 ≥ corePoolSize:尝试将任务放入队列。

  4. 队列已满 && 线程数 < maximumPoolSize:创建非核心线程执行任务。

  5. 队列满 && 已达最大线程数:执行拒绝策略(默认抛异常)。


2.3.2 任务缓冲机制

任务队列用于缓存尚未执行的任务:

队列类型特性
ArrayBlockingQueue有界 FIFO 队列,避免内存溢出
LinkedBlockingQueue默认无界队列,适合任务速率平稳
SynchronousQueue不存储任务,适用于高并发
PriorityBlockingQueue支持优先级任务

任务是否入队,决定了线程是否扩容。


2.3.3 任务申请(线程取任务)

任务的获取由 getTask() 方法完成:

  • 优先从队列中 poll 一个任务

  • 若获取失败,且超出 keepAliveTime,线程会退出

  • 如果线程池关闭,线程立即退出


2.3.4 任务拒绝策略

当线程池无法接收任务时,会调用 RejectedExecutionHandler

策略描述
AbortPolicy(默认)抛出异常
DiscardPolicy直接丢弃任务
DiscardOldestPolicy丢弃队列中最老的任务
CallerRunsPolicy调用线程自己执行任务(削峰)

合理的拒绝策略有助于保护系统稳定性。


2.4 Worker 线程管理机制

2.4.1 Worker 线程

Worker 是线程池中用于执行任务的线程封装类,它本质是一个实现了 Runnable 接口的任务执行单元,每个 Worker 包含:

  • 一个真正的 Thread 对象

  • 一个任务任务引用

  • 一个 run() 循环体:从队列中不断拉取任务执行


2.4.2 Worker 线程的创建(addWorker)

线程池根据当前任务和线程数决定是否调用 addWorker() 增加线程:

  • 当线程数 < corePoolSize:创建核心线程

  • 当队列已满 && 线程数 < maximumPoolSize:创建临时线程

使用 ThreadFactory 可定制线程名称、优先级等。


2.4.3 Worker 线程的回收

非核心线程超过 keepAliveTime 会被自动回收:

  • 降低资源占用

  • 避免长期占用 CPU/内存

  • 通过 allowCoreThreadTimeOut(true) 也可使核心线程超时回收

回收逻辑在 getTask() 中实现。


2.4.4 Worker 线程执行任务流程

Worker 启动后,在 run() 方法中循环调用:

while ((task != null || (task = getTask()) != null)) {beforeExecute()try {task.run();} finally {afterExecute()}
}

执行完任务后尝试从队列中取下一个任务,直到线程超时或线程池关闭。


总结

Java 的线程池设计是非常经典的“并发容器”之一,其优雅地处理了:

  • 线程的 复用与销毁

  • 任务的 排队与拒绝

  • 系统的 稳定性与扩展性

它不是简单的任务线程分发器,更是一个具备“智能调度、弹性扩容、精细管控”能力的多线程平台。


附录:推荐配置建议

场景核心参数建议
接口服务corePoolSize = CPU 核心数,队列有限,拒绝策略为 CallerRuns
IO 密集maximumPoolSize 设置略高,使用 SynchronousQueue
定时任务使用 ScheduledThreadPoolExecutor
高并发网关使用自定义线程工厂 + 有界队列 + 指标监控

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86864.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86864.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/86864.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【3.3】Pod详解——容器探针部署第一个pod

文章目录 容器探针小知识-控制平面Pod实战声明式模型&命令模式 部署第一个pod编写pod清单文件kubectl命令将清单文件post到api-server验证pod删除pod 容器探针 上面已经讲到容器状态,那么这些容器的状态是怎么检测到的呢?实际上在pod中有三种探针&#xff0c;存活探针(li…

Insar 相位展开真实的数据集的生成与下载(随机矩阵放大,zernike 仿真包裹相位)

1.真实的数据集下载: Delta-X: UAVSAR L1B Interferometric Products, MRD, Louisiana, 2021 | NASA Earthdata 注意下载的时候需要注册登录一下哦 2. 适用于 深度学习训练的数据集 通过网盘分享的文件:InSAR-DLPU.rar 链接: https://pan.baidu.com/s/1CRWAuNYwCHP_iqCeIhf…

C++ 多线程深度解析:掌握并行编程的艺术与实践

在现代软件开发中&#xff0c;多线程&#xff08;multithreading&#xff09;已不再是可选项&#xff0c;而是提升应用程序性能、响应速度和资源利用率的核心技术。随着多核处理器的普及&#xff0c;如何让代码有效地利用这些硬件资源&#xff0c;成为每个 C 开发者必须掌握的技…

(线性代数)矩阵的奇异值Singular Value

矩阵的奇异值是矩阵分析中一个非常重要的概念&#xff0c;尤其是在数值线性代数、数据降维&#xff08;如PCA&#xff09;、图像处理等领域有着广泛应用。奇异值分解&#xff08;SVD, Singular Value Decomposition&#xff09;是一种强大的工具&#xff0c;可以将任意形状的矩…

数据结构复习4

第四章 串 一些面试题 12. 介绍一下KMP算法。★★★ KMP算法是一种高效的字符串匹配算法&#xff0c;用于在一个文本串中查找一个模式串的出现位置。KMP算法通过利用模式串自身的信息&#xff0c;在匹配过程中避免不必要的回溯&#xff0c;从而提高匹配效率。 KMP算法的核心思…

【八股消消乐】消息队列优化—消息有序

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《八股消消乐》旨在记录个人所背的八股文&#xff0c;包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点&#xff…

2D写实交互数字人如何重塑服务体验?

在数字化浪潮席卷全球的当下&#xff0c;人机交互模式正经历着前所未有的变革。从早期的文本命令行界面&#xff0c;到图形用户界面&#xff08;GUI&#xff09;的普及&#xff0c;再到如今语音交互、手势识别等多模态交互技术的兴起&#xff0c;我们与机器之间的沟通方式愈发自…

CI/CD GitHub Actions配置流程

腾讯云服务器宝塔FinalShellgithup 1.在云服务器上创建SSH秘钥对&#xff0c;下载秘钥到本地 2.在服务器中绑定秘钥对&#xff08;绑定后&#xff0c;服务器不能将不允许密码登录&#xff09;绑定前先关机服务器&#xff0c;绑定后再开启服务器 3.FinalShell改为公钥登录&am…

液态交互效果网页开发--源自鸿蒙5以及iOS26的灵感

首先先来看看最终展示效果 当鼠标靠近“开始探索”的按钮的时候&#xff0c;按钮放大并有微弱光效 鼠标靠近之前会给视窗添加一层接近背景的朦胧感&#xff0c;当鼠标放在视窗上朦胧感消失 技术不复杂&#xff0c;这个网页主要是使用了以下关键技术&#xff1a; HTML5 语义化标…

PYTHON从入门到实践9-类和实例

# 【1】面向对象编程 class Student(object):# 可以帮属性值绑定到对象上&#xff0c;self相当于JAVA的thisdef __init__(self, name, age):self.name nameself.age agedef speak(self):print(self.name, 说&#xff1a;老师好)if __name__ __main__:new_student1 Student(…

matplotlib 绘制极坐标图

1、功能介绍&#xff1a; 使用了 matplotlib 库来创建一个极坐标图 2、代码部分&#xff1a; import matplotlib.pyplot as plt import numpy as np# 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] # 选择黑体字体&#xff0c;支持中文 plt.rcParams[axes.unicode…

Dask心得与笔记【2】

文章目录 计算参考文献 计算 数组切片如下 import numpy as np import dask.array as dadata np.arange(1000).reshape(10, 100) a da.from_array(data, chunks(5, 20)) print(a[:,0:3])切片结果是前3列 dask.array<getitem, shape(10, 3), dtypeint64, chunksize(5, 3…

数据采集合规安全是品牌控价基石

在品牌控价与数据分析工作中&#xff0c;数据采集是不可或缺的前置环节。当前主流的数据采集方式为爬虫采集&#xff0c;这种依托机器自动化操作的模式&#xff0c;取代了传统人工逐一浏览、复制数据的繁琐流程&#xff0c;大幅提升了效率。采集后的原始数据&#xff0c;会由系…

llm推理赋能action policy的探索

兄弟&#xff0c;你这个问题非常到位&#xff0c;咱分两个问题详细讲透&#xff1a; &#x1f680; (1) HybridVLA怎么引入更好的推理能力赋能Diffusion Action&#xff1f; HybridVLA 目前设计的亮点&#xff1a; Diffusion Token 与 LLM 自回归结合 但推理能力没有被显式结…

spring04-管理bean(创建、注入):基于注解

一、什么是注解&#xff1f; &#xff08;1&#xff09;注解的定义 注解&#xff08;Annotation&#xff09;是 Java 代码中的一种特殊标记&#xff0c;用于在程序运行或编译时提供元信息。 格式&#xff1a; 注解名(属性名属性值, 属性名属性值...)&#xff08;2&#xff…

docker安装elasticsearch和kibana

elasticsearch版本和kibana版本需保持一致。这里我使用的都是8.18.2 安装elasticsearch docker-compose.yml networks:es-net: external: true services:elasticsearch:container_name: es01deploy:resources:limits:cpus: 0memory: 0environment:- discovery.typesingle-no…

Python爬虫实战:研究sanitize库相关技术

1. 引言 1.1 研究背景与意义 在当今数字化时代,互联网已成为人们获取信息、交流互动的重要平台。随着 Web 2.0 技术的发展,用户生成内容 (UGC)、社交媒体嵌入、第三方插件等功能极大丰富了网页的内容和交互性,但也带来了严峻的安全挑战。根据 Web 应用安全联盟 (WAS) 的统…

c++ 学习(二、结构体)

目录 一、结构体与const 二、结构体与class的区别 参考链接&#xff1a;69 结构体-结构体中const使用场景_哔哩哔哩_bilibili 一、结构体与const 调用函数的时候&#xff0c;希望这个结构体是可读而不可写的时候&#xff0c;传指针&#xff0c;使用const修饰&#xff0c;方式…

机器学习开篇:算法分类与开发流程

种一棵树最好的时间是十年前&#xff0c;其次是现在。 一、机器学习算法分类 机器学习&#xff08;ML&#xff0c;Meachine Learning&#xff09;是人工智能的核心领域&#xff0c;让计算机从数据中学习规律并做出预测&#xff0c;本文简单介绍机器学习的算法分类和开发流程。…

使用pyflink编写demo并将任务提交到yarn集群

目录 背景 一、pyflink安装 二、编写demo程序 三、提交yarn前准备 四、提交任务 五、踩坑记录 1、提交任务时客户端出现语法错误 2、提交任务时客户端出现lzma包找不到 3、提交任务时客户端出现“org.apache.flink.streaming.api.utils.PythonTypeUtils.getCollectionIn…