分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南


title: java线程池使用 author: 哪吒 date: '2023-06-15'

点击勘误issues,哪吒感谢大家的阅读

Java线程池使用指南

1. 线程池基础使用

1.1 创建线程池的方式

方式一:使用Executors工具类(不推荐)
// 1. 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);// 2. 缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();// 3. 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();// 4. 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);

为什么不推荐使用Executors?

问题分析:
┌─────────────────────────────────────────────────────────┐
│  newFixedThreadPool & newSingleThreadExecutor          │
│  ↓                                                     │
│  使用LinkedBlockingQueue(无界队列)                    │
│  ↓                                                     │
│  可能导致内存溢出(OOM)                                │
│                                                         │
│  newCachedThreadPool                                    │
│  ↓                                                     │
│  最大线程数为Integer.MAX_VALUE                          │
│  ↓                                                     │
│  可能创建大量线程导致系统崩溃                            │
└─────────────────────────────────────────────────────────┘
方式二:手动创建ThreadPoolExecutor(推荐)
public class ThreadPoolFactory {/*** 创建标准线程池*/public static ThreadPoolExecutor createStandardPool() {returnnew ThreadPoolExecutor(5,                                      // 核心线程数10,                                     // 最大线程数60L,                                    // 空闲时间TimeUnit.SECONDS,                       // 时间单位new ArrayBlockingQueue<>(100),          // 工作队列new ThreadFactory() {                   // 线程工厂privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "CustomPool-" + threadNumber.getAndIncrement());t.setDaemon(false);  // 设置为用户线程t.setPriority(Thread.NORM_PRIORITY);return t;}},new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略);}
}

2. 常用线程池类型及应用场景

2.1 CPU密集型任务线程池

public class CPUIntensiveThreadPool {/*** CPU密集型任务线程池配置* 核心线程数 = CPU核心数 + 1*/public static ThreadPoolExecutor createCPUIntensivePool() {int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;returnnew ThreadPoolExecutor(corePoolSize,corePoolSize,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(50),new ThreadFactory() {privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "CPU-Pool-" + threadNumber.getAndIncrement());t.setDaemon(false);return t;}},new ThreadPoolExecutor.AbortPolicy());}// 使用示例:计算密集型任务public static void main(String[] args) {ThreadPoolExecutor executor = createCPUIntensivePool();// 提交计算任务for (int i = 0; i < 10; i++) {finalint taskId = i;executor.submit(() -> {long result = fibonacci(35); // 计算斐波那契数列System.out.println("任务" + taskId + "计算结果:" + result + " - 线程:" + Thread.currentThread().getName());});}shutdownGracefully(executor);}private static long fibonacci(int n) {if (n <= 1) return n;return fibonacci(n - 1) + fibonacci(n - 2);}private static void shutdownGracefully(ExecutorService executor) {executor.shutdown();try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}

2.2 IO密集型任务线程池

public class IOIntensiveThreadPool {/*** IO密集型任务线程池配置* 核心线程数 = CPU核心数 * 2*/public static ThreadPoolExecutor createIOIntensivePool() {int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;returnnew ThreadPoolExecutor(corePoolSize,corePoolSize * 2,60L,TimeUnit.SECONDS,new LinkedBlockingQueue<>(200),new ThreadFactory() {privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "IO-Pool-" + threadNumber.getAndIncrement());t.setDaemon(false);return t;}},new ThreadPoolExecutor.CallerRunsPolicy());}// 使用示例:文件读写任务public static void main(String[] args) {ThreadPoolExecutor executor = createIOIntensivePool();// 提交IO任务for (int i = 0; i < 20; i++) {finalint taskId = i;executor.submit(() -> {try {// 模拟文件读写操作Thread.sleep(1000); // 模拟IO等待System.out.println("任务" + taskId + "完成文件操作 - 线程:" + Thread.currentThread().getName());} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}shutdownGracefully(executor);}private static void shutdownGracefully(ExecutorService executor) {executor.shutdown();try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}

2.3 定时任务线程池

public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(3,new ThreadFactory() {privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "Scheduler-" + threadNumber.getAndIncrement());t.setDaemon(false);return t;}});// 1. 延迟执行任务scheduler.schedule(() -> {System.out.println("延迟3秒执行的任务 - " + new Date());}, 3, TimeUnit.SECONDS);// 2. 固定频率执行任务ScheduledFuture<?> fixedRateTask = scheduler.scheduleAtFixedRate(() -> {System.out.println("每2秒执行一次的任务 - " + new Date());}, 1, 2, TimeUnit.SECONDS);// 3. 固定延迟执行任务ScheduledFuture<?> fixedDelayTask = scheduler.scheduleWithFixedDelay(() -> {System.out.println("上次执行完成后延迟1秒再执行 - " + new Date());try {Thread.sleep(500); // 模拟任务执行时间} catch (InterruptedException e) {Thread.currentThread().interrupt();}}, 1, 1, TimeUnit.SECONDS);// 运行10秒后停止Thread.sleep(10000);fixedRateTask.cancel(false);fixedDelayTask.cancel(false);scheduler.shutdown();}
}

3. 线程池监控与管理

3.1 线程池状态监控

public class ThreadPoolMonitor {/*** 创建可监控的线程池*/public static ThreadPoolExecutor createMonitorablePool() {returnnew ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),new ThreadFactory() {privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "Monitor-Pool-" + threadNumber.getAndIncrement());t.setDaemon(false);return t;}},new ThreadPoolExecutor.CallerRunsPolicy()) {@Overrideprotected void beforeExecute(Thread t, Runnable r) {super.beforeExecute(t, r);System.out.println("任务开始执行 - 线程:" + t.getName());}@Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);if (t != null) {System.err.println("任务执行异常:" + t.getMessage());} else {System.out.println("任务执行完成");}}@Overrideprotected void terminated() {super.terminated();System.out.println("线程池已终止");}};}/*** 打印线程池状态信息*/public static void printPoolStatus(ThreadPoolExecutor executor) {System.out.println("\n=== 线程池状态信息 ===");System.out.println("核心线程数:" + executor.getCorePoolSize());System.out.println("最大线程数:" + executor.getMaximumPoolSize());System.out.println("当前线程数:" + executor.getPoolSize());System.out.println("活跃线程数:" + executor.getActiveCount());System.out.println("队列中任务数:" + executor.getQueue().size());System.out.println("已完成任务数:" + executor.getCompletedTaskCount());System.out.println("总任务数:" + executor.getTaskCount());System.out.println("是否关闭:" + executor.isShutdown());System.out.println("是否终止:" + executor.isTerminated());System.out.println("========================\n");}
}

3.2 线程池异常处理

public class ThreadPoolExceptionHandling {/*** 创建带异常处理的线程池*/public static ThreadPoolExecutor createSafeThreadPool() {returnnew ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(50),new ThreadFactory() {privatefinal AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r, "Safe-Pool-" + threadNumber.getAndIncrement());t.setDaemon(false);// 设置未捕获异常处理器t.setUncaughtExceptionHandler((thread, ex) -> {System.err.println("线程 " + thread.getName() + " 发生未捕获异常:" + ex.getMessage());ex.printStackTrace();});return t;}},new ThreadPoolExecutor.CallerRunsPolicy());}/*** 安全任务包装器*/public static Runnable wrapTask(Runnable task) {return () -> {try {task.run();} catch (Exception e) {System.err.println("任务执行异常:" + e.getMessage());e.printStackTrace();// 可以在这里添加异常上报逻辑}};}public static void main(String[] args) {ThreadPoolExecutor executor = createSafeThreadPool();// 提交可能抛异常的任务executor.submit(wrapTask(() -> {System.out.println("正常任务执行");}));executor.submit(wrapTask(() -> {thrownew RuntimeException("模拟任务异常");}));// 使用Future处理异常Future<?> future = executor.submit(() -> {thrownew RuntimeException("Future异常");});try {future.get();} catch (ExecutionException e) {System.err.println("通过Future捕获异常:" + e.getCause().getMessage());} catch (InterruptedException e) {Thread.currentThread().interrupt();}executor.shutdown();}
}

4. 最佳实践与注意事项

4.1 线程池参数配置指南

public class ThreadPoolConfigGuide {/*** 根据任务类型配置线程池*/publicstaticclass ThreadPoolConfigurator {// CPU密集型任务配置public static ThreadPoolExecutor forCPUIntensive() {int processors = Runtime.getRuntime().availableProcessors();returnnew ThreadPoolExecutor(processors,                    // 核心线程数 = CPU核心数processors,                    // 最大线程数 = CPU核心数0L, TimeUnit.MILLISECONDS,     // 无空闲时间new ArrayBlockingQueue<>(processors * 2), // 队列大小适中new ThreadPoolExecutor.AbortPolicy());}// IO密集型任务配置public static ThreadPoolExecutor forIOIntensive() {int processors = Runtime.getRuntime().availableProcessors();returnnew ThreadPoolExecutor(processors * 2,                // 核心线程数 = CPU核心数 * 2processors * 4,                // 最大线程数 = CPU核心数 * 460L, TimeUnit.SECONDS,         // 空闲60秒回收new LinkedBlockingQueue<>(1000), // 较大的队列new ThreadPoolExecutor.CallerRunsPolicy());}// 混合型任务配置public static ThreadPoolExecutor forMixed() {int processors = Runtime.getRuntime().availableProcessors();returnnew ThreadPoolExecutor(processors + 1,                // 核心线程数 = CPU核心数 + 1processors * 2,                // 最大线程数 = CPU核心数 * 260L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(200),new ThreadPoolExecutor.CallerRunsPolicy());}}
}

4.2 常见问题与解决方案

public class ThreadPoolTroubleshooting {/*** 问题1:线程池任务积压* 解决方案:动态调整线程池大小*/publicstaticclass DynamicThreadPool {privatefinal ThreadPoolExecutor executor;privatefinal ScheduledExecutorService monitor;public DynamicThreadPool(ThreadPoolExecutor executor) {this.executor = executor;this.monitor = Executors.newSingleThreadScheduledExecutor();startMonitoring();}private void startMonitoring() {monitor.scheduleAtFixedRate(() -> {int queueSize = executor.getQueue().size();int activeCount = executor.getActiveCount();int corePoolSize = executor.getCorePoolSize();int maxPoolSize = executor.getMaximumPoolSize();// 队列积压严重,增加线程if (queueSize > 100 && activeCount >= corePoolSize * 0.8) {int newCoreSize = Math.min(corePoolSize + 1, maxPoolSize);if (newCoreSize > corePoolSize) {executor.setCorePoolSize(newCoreSize);System.out.println("增加核心线程数至:" + newCoreSize);}}// 队列空闲,减少线程if (queueSize < 10 && activeCount < corePoolSize * 0.5 && corePoolSize > 2) {executor.setCorePoolSize(corePoolSize - 1);System.out.println("减少核心线程数至:" + (corePoolSize - 1));}}, 0, 30, TimeUnit.SECONDS);}}/*** 问题2:任务执行时间过长* 解决方案:任务超时控制*/publicstaticclass TimeoutTaskExecutor {privatefinal ThreadPoolExecutor executor;public TimeoutTaskExecutor(ThreadPoolExecutor executor) {this.executor = executor;}public <T> T executeWithTimeout(Callable<T> task, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {Future<T> future = executor.submit(task);try {return future.get(timeout, unit);} catch (TimeoutException e) {future.cancel(true); // 取消任务throw e;}}}
}

4.3 性能优化建议

线程池性能优化清单:1. 参数配置优化✓ 根据任务类型选择合适的核心线程数✓ 设置合理的最大线程数和队列大小✓ 选择适当的拒绝策略2. 任务设计优化✓ 避免任务执行时间过长✓ 合理拆分大任务✓ 避免任务间的强依赖关系3. 监控与调优✓ 定期监控线程池状态✓ 记录任务执行时间✓ 根据监控数据调整参数4. 资源管理✓ 及时关闭线程池✓ 避免创建过多线程池✓ 合理设置线程优先级

5. 总结

Java线程池是并发编程的重要工具,正确使用线程池可以:

  • 提高性能:减少线程创建和销毁的开销

  • 控制资源:限制并发线程数量,避免系统资源耗尽

  • 提高响应性:复用线程,快速响应任务请求

  • 便于管理:统一管理线程生命周期

关键要点

  1. 避免使用Executors创建线程池,推荐手动创建ThreadPoolExecutor

  2. 根据任务类型(CPU密集型/IO密集型)合理配置参数

  3. 实施有效的监控和异常处理机制

  4. 注意线程池的优雅关闭

  5. 定期评估和调优线程池配置

通过遵循这些最佳实践,可以充分发挥线程池的优势,构建高性能、稳定的并发应用程序。

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

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

相关文章

【最新版】点大全能版v2.6.7.1 含汇付斗拱插件+uniapp前端

一.介绍V2全能版本、独立版本全开源&#xff0c;含链动21&#xff0c;汇付斗拱​、排队免单、推三返1 &#xff0c;扶持金&#xff0c;平级奖&#xff0c;团队业绩奖&#xff0c;酒店管理&#xff0c;约车&#xff0c;餐饮等众多营销功能&#xff0c;商城系统版本号为2.6.7.1&a…

Go语言高级面试必考:切片(slice)你真的掌握了吗?

目录 1. 切片是个啥?从数组到切片的灵魂进化 数组与切片的爱恨情仇 切片的内存结构:三巨头共舞 切片的初始化方式:灵活到飞起 切片的“引用”特性:福也是祸 源码初探:切片的诞生 2. 切片三剑客:len、cap 和底层数组的三角恋 len 和 cap 的微妙关系 切片共享的秘密…

monorepo + Turborepo --- 开发应用程序

目录 配置开发任务 在 dev 之前运行设置任务 运行特定应用程序 使用终端 UI 与任务交互 监听模式 watch 将 turbo watch 与持久任务一起使用 依赖感知的持久任务 没有依赖感知的持久任务 缓存 任务输出 局限性 在 Monorepo 中开发应用程序可以解锁强大的工作流程&…

C#字符串相关库函数运用梳理总结 + 正则表达式详解

C# 字符串常用库函数总结 &#x1f539; 1. 字符串比较 方法说明示例string.Equals()比较两个字符串是否相等&#xff08;可忽略大小写&#xff09;string.Equals("abc", "ABC", StringComparison.OrdinalIgnoreCase) / !判断两个字符串是否相等/不等&quo…

投机采样(Speculative Decoding)

投机采样&#xff08;Speculative Decoding&#xff09; 是一种加速大型语言模型&#xff08;LLM&#xff09;推理的技术&#xff0c;其核心思想是通过预生成候选token序列并异步校验&#xff0c;从而减少主模型的计算量&#xff0c;同时保持生成结果的准确性。 核心思想是通过…

如何将华为手机中的照片传输到电脑

华为手机在众多手机品牌中以其出色的品质脱颖而出&#xff0c;尤其是其摄像头功能。有时&#xff0c;你可能在华为手机上积累了太多有意义的照片&#xff0c;想要将这些照片上传到电脑以释放手机存储空间。然而&#xff0c;出于用户信息安全的考虑&#xff0c;一些便捷的方法可…

whitt算法之特征向量的尺度

whitt中特征值不相等判别条件另一个条件的意思&#xff0c; 实际上这两个条件都没用&#xff0c;不用看&#xff0c;特征值排序&#xff0c;如果现在顺序对λ1/λ1‘ w λ2/λ2 -w 此时取相位就是0&#xff0c;最小了 如果相反就是面的是0我的代码用最优相位内积去交换位置公…

【Note】《深入理解Linux内核》 第十九章:深入理解 Linux 进程通信机制

《深入理解Linux内核》 第十九章&#xff1a;深入理解 Linux 进程通信机制&#xff08;Process Communication&#xff09;关键词&#xff1a;IPC、信号、管道、FIFO、消息队列、信号量、共享内存、套接字、内核对象、同步机制一、进程通信概述 1.1 为什么需要进程通信 在 Linu…

【Mac 从 0 到 1 保姆级配置教程 19】- 英语学习篇-我的英语工作流分享(AI 辅助学习)

文章目录前言听力沉浸式翻译阅读Easydict配置自定义字典&#xff08;重点&#xff09;欧陆词典沙拉查词沉浸式翻译写作Eearthworm英文提问口语最后学习资料系列教程前言 本文介绍一下我日常如何学习和使用英语的工作流&#xff0c;包括一些常用好用的工具&#xff0c;好的工具…

从库函数到API接口,深挖不同语言背后的“封装”与“调用”思想

个人主页-爱因斯晨 优秀文章推荐 文章目录个人主页-爱因斯晨优秀文章推荐引言一、三种调用机制概述C语言的库函数Python 的导包机制Java 的 API 接口调用综上&#xff1a;二、它们的相同点&#xff1a;封装与调用三、不同之处**对比核心维度****细节串讲**1. **C 语言&#xf…

基于NCNN框架在Android平台实现YOLOv8目标检测模型的高效部署与实践

随着移动设备计算能力的提升&#xff0c;越来越多的深度学习模型被部署到移动端&#xff0c;以实现实时、低延迟的应用场景。YOLO系列的在目标检测任务中表现出色&#xff0c;具有精度高、速度快的优势。本文将详细介绍如何基于NCNN框架 &#xff0c;在Android平台 上高效部署Y…

华为动态路由配置

问题描述&#xff1a;针对四个路由器在不同的网段场景中&#xff0c;对四个路由器进行动态路由配置。下面以如下场景为例&#xff0c;介绍详细配置过程。配置过程&#xff1a; 1、每个路由器的接口配置IP地址 路由器AR1中每个接口配置IP地址。 sys # 进入系统视图 interface g…

分布式事务解决方案(三)

在Java分布式系统领域&#xff0c;传统强一致性方案&#xff08;如2PC、3PC&#xff09;在高并发、复杂业务场景下暴露出性能瓶颈和阻塞问题。而Saga模式与事件溯源&#xff08;Event Sourcing&#xff09;作为更具弹性和扩展性的解决方案&#xff0c;逐渐成为分布式事务处理和…

【时时三省】(C语言基础)通过指针引用数组

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省数组元素的指针一个变量有地址&#xff0c;一个数组包含若干元素&#xff0c;每个数组元素都在内存中占用存储单元&#xff0c;它们都有相应的地址。指针变量既然可以指向变量&#xff0c;当然…

【WEB】Polar靶场 21-25题 详细笔记

二十一.php very nicephp又是你 ,但是经过这么多次折磨后我感觉我已经有一点抗性了老规矩&#xff0c;先看知识点PHP 序列化是将 PHP 变量&#xff08;如对象、数组&#xff09;转换为字符串的过程&#xff0c;便于存储或传输。反序列化则是将字符串还原为原始变量。这在缓存、…

【Guava】1.0.设计虚拟机的方向

【Guava】1.0.设计虚拟机的方向虚拟机是什么&#xff1f;栈式虚拟机栈式虚拟机的优缺点题外话虚拟机是什么&#xff1f; 虚拟机&#xff08;VirtualMachine, VM&#xff09;是一种计算机程序或系统&#xff0c;它通过软件模拟物理计算机的硬件运行环境&#xff0c;使得多个操作…

[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的高校实验室资源综合管理系统,推荐!

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本高校实验室资源综合管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大…

Spring Boot:影响事务回滚的几种情况

一、Controller 捕获异常导致事务失效 需求 我们有一个用户注册服务&#xff0c;注册时需要&#xff1a; 创建用户账户分配初始积分发送注册通知 这三个操作需要在同一个事务中执行&#xff0c;任何一步失败都要回滚。 错误示例&#xff1a;Controller 捕获异常导致事务失效 Re…

如何避免分布式爬虫被目标网站封禁?

在分布式爬虫的大规模数据采集场景中&#xff0c;避免被目标网站封禁的核心逻辑是&#xff1a;通过技术手段模拟真实用户行为&#xff0c;降低爬虫行为的可识别性&#xff0c;同时建立动态适配机制应对网站反爬策略的升级。以下从请求伪装、行为控制、资源管理、反爬对抗四个维…

Maven 打包排除特定依赖的完整指南(详细方法 + 示例)

前言 在使用 Maven 构建 Java 项目时&#xff0c;我们常常需要对项目的打包过程进行精细化控制&#xff0c;尤其是希望排除某些特定的依赖库。这可能是为了减小最终构建产物的体积、避免版本冲突&#xff0c;或者仅仅是为了满足不同环境下的部署需求。 本文将详细介绍如何在 Ma…