Java多线程实现之线程池详解

Java多线程实现之线程池详解

    • 一、线程池的基本概念
      • 1.1 为什么需要线程池
      • 1.2 线程池的核心思想
    • 二、Java线程池的实现
      • 2.1 Executor框架
      • 2.2 ThreadPoolExecutor构造参数
    • 三、常见线程池类型
      • 3.1 FixedThreadPool
      • 3.2 CachedThreadPool
      • 3.3 SingleThreadExecutor
      • 3.4 ScheduledThreadPool
    • 四、线程池的工作流程
    • 五、线程池的使用示例
      • 5.1 提交Runnable任务
      • 5.2 提交Callable任务
      • 5.3 定时任务
    • 六、线程池的拒绝策略
      • 6.1 AbortPolicy(默认)
      • 6.2 CallerRunsPolicy
      • 6.3 DiscardPolicy
      • 6.4 DiscardOldestPolicy
    • 七、线程池的监控与调优
      • 7.1 监控线程池状态
      • 7.2 合理配置线程池大小
    • 八、线程池的最佳实践
      • 8.1 避免使用Executors工厂方法
      • 8.2 正确关闭线程池
      • 8.3 使用自定义线程工厂

线程池在Java中是一种重要工具,用于管理和复用线程资源,合理使用线程池可以提高程序性能、减少资源消耗,并简化线程管理。本文我将详细介绍Java线程池的实现原理、常见类型以及使用方法等等,帮你更好地理解和深入Java的多线程实现。

一、线程池的基本概念

1.1 为什么需要线程池

  • 线程创建和销毁开销大:频繁创建和销毁线程会消耗大量系统资源
  • 资源管理困难:无限制创建线程可能导致系统资源耗尽
  • 控制并发度:线程池可以限制同时运行的线程数量,避免过度并发

1.2 线程池的核心思想

线程池预先创建一定数量的线程,当有任务提交时,从线程池中获取线程执行任务,任务执行完毕后线程不会销毁,而是返回线程池等待下一个任务。

二、Java线程池的实现

2.1 Executor框架

Java通过Executor框架提供线程池的实现,核心接口和类如下:

  • Executor:线程池的基础接口,定义了执行任务的方法
  • ExecutorService:扩展了Executor,提供了管理线程池的方法
  • ThreadPoolExecutor:线程池的核心实现类
  • ScheduledExecutorService:支持定时任务的线程池接口
  • Executors:工具类,提供创建线程池的静态工厂方法

2.2 ThreadPoolExecutor构造参数

public ThreadPoolExecutor(int corePoolSize,                   // 核心线程数int maximumPoolSize,                // 最大线程数long keepAliveTime,                 // 空闲线程存活时间TimeUnit unit,                      // 时间单位BlockingQueue<Runnable> workQueue,  // 任务队列ThreadFactory threadFactory,        // 线程工厂RejectedExecutionHandler handler    // 拒绝策略
)

三、常见线程池类型

3.1 FixedThreadPool

固定大小的线程池,核心线程数和最大线程数相等:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

3.2 CachedThreadPool

可缓存的线程池,线程数根据需要动态调整:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

3.3 SingleThreadExecutor

单线程执行器,确保所有任务按顺序执行:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

3.4 ScheduledThreadPool

支持定时任务的线程池:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

四、线程池的工作流程

  1. 提交任务:调用execute()submit()方法提交任务
  2. 线程池判断
    • 如果当前线程数小于核心线程数,创建新线程执行任务
    • 如果当前线程数大于等于核心线程数,将任务放入任务队列
    • 如果任务队列已满且线程数小于最大线程数,创建新线程执行任务
    • 如果任务队列已满且线程数大于等于最大线程数,执行拒绝策略
  3. 任务执行完毕:线程返回线程池,等待下一个任务

五、线程池的使用示例

5.1 提交Runnable任务

ExecutorService executor = Executors.newFixedThreadPool(5);for (int i = 0; i < 10; i++) {final int taskId = i;executor.execute(() -> {System.out.println("执行任务: " + taskId);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕");});
}executor.shutdown(); // 关闭线程池

5.2 提交Callable任务

ExecutorService executor = Executors.newFixedThreadPool(3);Future<String> future = executor.submit(() -> {Thread.sleep(2000);return "任务执行结果";
});try {String result = future.get(); // 获取任务结果System.out.println("结果: " + result);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}executor.shutdown();

5.3 定时任务

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);// 延迟3秒后执行任务
scheduler.schedule(() -> {System.out.println("延迟任务执行");
}, 3, TimeUnit.SECONDS);// 延迟1秒后开始执行,每2秒执行一次
scheduler.scheduleAtFixedRate(() -> {System.out.println("定时任务执行");
}, 1, 2, TimeUnit.SECONDS);

六、线程池的拒绝策略

6.1 AbortPolicy(默认)

直接抛出RejectedExecutionException异常:

new ThreadPoolExecutor.AbortPolicy()

6.2 CallerRunsPolicy

由提交任务的线程自己执行该任务:

new ThreadPoolExecutor.CallerRunsPolicy()

6.3 DiscardPolicy

直接丢弃任务,不做任何处理:

new ThreadPoolExecutor.DiscardPolicy()

6.4 DiscardOldestPolicy

丢弃任务队列中最老的任务,然后尝试提交新任务:

new ThreadPoolExecutor.DiscardOldestPolicy()

七、线程池的监控与调优

7.1 监控线程池状态

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>()
);// 获取线程池状态
int activeCount = executor.getActiveCount(); // 活跃线程数
long completedTaskCount = executor.getCompletedTaskCount(); // 已完成任务数
int queueSize = executor.getQueue().size(); // 队列中的任务数

7.2 合理配置线程池大小

  • CPU密集型任务:线程数 = CPU核心数 + 1
  • IO密集型任务:线程数 = CPU核心数 * (1 + 平均等待时间/平均处理时间)

八、线程池的最佳实践

8.1 避免使用Executors工厂方法

Executors提供的工厂方法可能会创建出有资源耗尽风险的线程池,建议直接使用ThreadPoolExecutor构造函数:

ExecutorService executor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(100),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy()
);

8.2 正确关闭线程池

executor.shutdown(); // 平缓关闭,等待已提交任务执行完毕
// executor.shutdownNow(); // 立即关闭,尝试终止正在执行的任务try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}
} catch (InterruptedException e) {executor.shutdownNow();
}

8.3 使用自定义线程工厂

通过自定义线程工厂可以为线程设置有意义的名称,便于调试:

ThreadFactory namedThreadFactory = new ThreadFactory() {private final AtomicInteger threadNum = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "my-thread-" + threadNum.getAndIncrement());}
};

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ

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

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

相关文章

解码美元-黄金负相关:LSTM-Attention因果发现与黄金反弹推演

摘要&#xff1a;本文采用时间序列分析框架与自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;对黄金与美元指数的负相关关系进行量化拆解。通过构建包含宏观经济因子、市场情绪指标及地缘风险的三维分析模型&#xff0c;揭示当前贵金属市场的核心驱动逻辑&#xff0c…

Asp.Net Core SignalR导入数据

文章目录 前言一、安装包二、使用步骤1.实现SignalR Hub服务&#xff1a;2.实现CSV文件解析及数据导入服务3.控制器4.前端实现&#xff08;vue&#xff09; 三、关键技术点说明总结 前言 导入CSV文件中的数据到数据库&#xff0c;使用CsvHelper解析CSV文件&#xff0c;SqlBulk…

Modern C++(四)声明

4、声明 声明是将名字引入到cpp程序中&#xff0c;不是每条声明都声明实际的东西。定义是足以使该名字所标识的实体被使用的声明。声明包含以下几种&#xff1a; 函数定义模板声明模板显式实例化模板显式特化命名空间定义链接说明属性声明&#xff08;C11&#xff09;空声明&…

目标检测yolo算法

yolov5s&#xff1a; 从github官网下载yolov5的算法之后&#xff0c;配置好环境&#xff08;pycharm安装包-CSDN博客&#xff09;&#xff0c;再下载权重文件&#xff0c;比如默认的yolov5s.pt&#xff1b; 运行当前文件&#xff08;detect.py&#xff09;&#xff0c;就能看…

一个超强的推理增强大模型,开源了,本地部署

大家好&#xff0c;我是 Ai 学习的老章 前几天介绍了MOE 模型先驱 Mistral 开源的代码 Agent 大模型——mistralai/Devstral-Small-2505 今天一起看看 Mistral 最新开源的推理大模型——Magistral Magistral 简介 Mistral 公司推出了首个推理模型 Magistral 及自研可扩展强…

MySQL体系架构解析(五):读懂MySQL日志文件是优化与故障排查的关键

MySQL文件 日志文件 在服务器运行过程中&#xff0c;会产生各种各样的日志&#xff0c;比如常规的查询日志&#xff0c;错误日志、二进制日志、 redo 日志和 Undo 日志等&#xff0c;日志文件记录了影响 MySQL 数据库的各种类型活动。 常见的日志文件有&#xff1a;错误日志…

湖南省网络建设与运维赛项竞赛规程及样题

湖南省职业院校技能竞赛样题 赛题说明 一、竞赛内容 “网络建设与运维”竞赛共分三个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;职业规范与素养 &#xff08; 5 分&#xff09; 第二部分&#xff1a;网络搭建及安全部署项目 &#xff08; 50 分&#xff09…

华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio搭建AnythingLLM聊天助手

华为云FlexusDeepSeek征文 | 基于华为云ModelArts Studio搭建AnythingLLM聊天助手 引言一、ModelArts Studio平台介绍华为云ModelArts Studio简介ModelArts Studio主要特点 二、AnythingLLM介绍AnythingLLM 简介AnythingLLM主要特点AnythingLLM地址 三、安装AnythingLLM应用下载…

板凳-------Mysql cookbook学习 (十--5)

6.11 计算年龄 2025年6月11日星期三 --创建表、初始化数据 drop table if exists sibling; create table sibling (name char(20),birth date );insert into sibling (name,birth) values(Gretchen,1942-04-14); insert into sibling (name,birth) values(Wilbur,1946-11-28)…

SAP RESTFUL接口方式发布SICF实现全路径

其他相关资料帖可参考&#xff1a; https://blog.csdn.net/woniu_maggie/article/details/146210752 https://blog.csdn.net/SAPmatinal/article/details/134349125 https://blog.csdn.net/weixin_44382089/article/details/128283417 【业务场景】 外部系统不想通过RFC (需…

在windows中安装或卸载nginx

首先在nginx的安装目录下cmd查看nginx的版本&#xff1a; 在看windows的服务中是否nginx注册为服务了 如果注册了服务就先将服务卸载了 在nginx的安装目录cmd执行命令 NginxService.exe uninstall “NginxService”是对应的注册的服务名称 关闭所有的相关nginx的服务这个也…

FaceFusion 技术深度剖析:核心算法与实现机制揭秘

在 AI 换脸技术蓬勃发展的浪潮中&#xff0c;FaceFusion 凭借其出色的换脸效果和便捷的操作&#xff0c;成为众多用户的首选工具。从短视频平台上的创意恶搞视频&#xff0c;到影视制作中的特效合成&#xff0c;FaceFusion 都展现出强大的实用性。而这一切的背后&#xff0c;是…

2. Web网络基础 - 协议端口

深入解析协议端口与netstat命令&#xff1a;网络工程师的实战指南 在网络通信中&#xff0c;协议端口是服务访问的门户。本文将全面解析端口概念&#xff0c;并通过netstat命令实战演示如何监控网络连接状态。 一、协议端口核心知识解析 1. 端口号的本质与分类 端口范围类型说…

嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析

vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); 函数第一个参数为消息队列等待插入链表&#xff0c; void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); /…

Ubuntu 配置使用 zsh + 插件配置 + oh-my-zsh 美化过程

Ubuntu 配置使用 zsh 插件配置 oh-my-zsh 美化过程 引言zsh 安装及基础配置oh-my-zsh 安装及美化配置oh-my-zsh 安装主题美化配置主题自定义主题 插件安装及配置官方插件查看及启用插件安装 主题文件备份.zshrcre5et_self.zsh-theme 同步发布在个人笔记Ubuntu 配置使用 zsh …

Xilinx FPGA 重构Multiboot ICAPE2和ICAPE3使用

一、FPGA Multiboot 本文主要介绍基于IPROG命令的FPGA多版本重构&#xff0c;用ICAP原语实现在线多版本切换。需要了解MultiBoot Fallback点击链接。 如下图所示&#xff0c;ICAP原语可实现flash中n1各版本的动态切换&#xff0c;在工作过程中&#xff0c;可以通过IPROG命令切…

springMVC-11 中文乱码处理

前言 本文介绍了springMVC中文乱码的解决方案&#xff0c;同时也贴出了本人遇到过的其他乱码情况&#xff0c;可以根据自身情况选择合适的解决方案。 其他-jdbc、前端、后端、jsp乱码的解决 Tomcat导致的乱码解决 自定义中文乱码过滤器 老方法&#xff0c;通过javaW…

mysql-innoDB存储引擎事务的原理

InnoDB 存储引擎支持 ACID 事务&#xff0c;其事务机制是通过 Redo Log&#xff08;重做日志&#xff09;、Undo Log&#xff08;回滚日志&#xff09; 和 事务日志系统 来实现的。下面详细解析 InnoDB 事务的工作原理。 1.事务的基本特性&#xff08;ACID&#xff09; 特性描…

在GIS 工作流中实现数据处理

通过将 ArcPy 应用于实际的 GIS 工作流&#xff0c;我们可以高效地完成数据处理任务&#xff0c;节省大量时间和精力。接下来&#xff0c;本文将结合具体案例&#xff0c;详细介绍如何运用 ArcPy 实现 GIS 数据处理的全流程。 数据读取与合并 假设我们有多个 shapefile 文件&a…

第十四届蓝桥杯_省赛B组(C).冶炼金属

题目如下: 拿到题我们来看一下&#xff0c;题目的意思&#xff0c;就是求出N个记录中的最大最小值&#xff0c;言外之意就是&#xff0c;如果超过了这个最大值不行&#xff0c;如果小于这个最小值也不行&#xff0c;所以我们得出&#xff0c;这道题是一个二分答案的题目&#x…