当前位置: 首页 > news >正文

Java线程池那点事

线程的生命周期

NEW -> RUNNABLE -> BLOCKED -> WAITING -> TIMED_WAIT -> TERMINATED

线程池

线程池参数

  1. int corePoolSize -- 核心线程数
  2. int maximumPoolSize -- 最大线程数
  3. long keepAliveTime -- 非核心线程探活时间
  4. TimeUnit unit -- 非核心线程探活时间单位
  5. BlockingQueue<Runnable> workQueue -- 阻塞队列
  6. RejectedExecutionHandler handler -- 拒绝策略

如何手动启动核心线程

  1. prestartAllCoreThreads():启动所有核心线程并返回启动的线程数。
  2. prestartCoreThread():启动一个线程,等待任务。如果已达到核心线程数,这个方法返回 false,否则返回 true。

线程池的工作原理

  1. 任务到达时先判断是否有空闲线程,如果有则使用空闲线程。
  2. 如果没有空闲线程,则判断线程数是否大于核心线程数,如果小于核心线程数则创建新的线程。
  3. 如果大于核心线程数,则将任务加入到阻塞队列。
  4. 当阻塞队列满时,则创建非核心线程,如果线程数大于等于最大线程数,则走拒绝策略。
  5. 当一定时间没有任务后,非核心线程就会自动销毁。

线程池拒绝策略

  1. 丢弃任务,抛异常(默认)。
  2. 丢弃任务,不抛异常。
  3. 丢弃队列前面的任务(最旧的任务),从新提交被拒绝的任务。
  4. 由调用线程来执行。

创建线程池需要注意哪些点?

  1. 设置合理的核心线程数以及最大线程数,避免OOM。
  2. 设置阻塞队列的长度,避免OOM。
  3. 自定义线程工厂,为创建的线程设置名称。
  4. 设置合理的线程活跃时间以及时间单位,有利于非核心线程的回收。
  5. 选择合适的拒绝策略,默认抛出RejectedExecutionexception类型的Runtimeeexception。(队列满了,线程数已经达到了最大线程数)。
  6. 核心线程数建议设置为CPU核数,最大线程数建议设置为CPU核数*2(需要根据是否IO操作密集来决定)。

如何给线程池创建的线程设置名称?

// 创建自定义的ThreadFactory
ThreadFactory customThreadFactory = newCustomThreadFactory("MyThreadPool");// 使用自定义的ThreadFactory创建线程池
ExecutorService executor = newThreadPoolExecutor( 2, 4, 10, TimeUnit.SECONDS, newArrayBlockingQueue<>(2), customThreadFactory);

线程池如何知道线程任务是否执行完?

  1. 通过 isTerminated() 判断线程池内是否还有线程在运行。
  2. 通过 submit() 方法提供的 Feture 返回值的 get()。
  3. 通过 CountDownLatch 计数器,设置计数值为 1,在代码块后面用 await() 阻塞,当计数值为 0 时,await() 会放行。
  4. 使用 shutdown() 和 awaitTermination()。shutdown() 关闭线程池不在接受新任务,awaitTermination() 等待所有任务执行完成。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class ThreadPoolExample {public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(10);// 提交一些任务for (int i = 0; i < 10; i++) {executorService.submit(() -> {// 模拟任务处理System.out.println("任务开始处理:" + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("任务处理完成:" + Thread.currentThread().getName());});}// 关闭线程池,不再接受新任务executorService.shutdown();// 等待所有任务完成if (executorService.awaitTermination(60, TimeUnit.SECONDS)) {System.out.println("所有任务都已处理完成");} else {System.out.println("有任务未能在指定时间内完成");}}
}

Executors线程池

  1. Executors.newCachedThreadPool(),缓存池。核心线程:0,最大线程:int.max,活跃时间:60s,队列:同步队列(SynchronousQueue,放入一个元素时,必须有一个线程准备好接收该元素,否则插入操作将阻塞,直到有线程来接收)。
  2. Executors.newFixedThreadPool(10),固定大小线程池。核心线程:10,最大线程:10,活跃时间:0s,队列:阻塞队列。
  3. Executors.newScheduledThreadPool(5),任务调度池。核心线程:5,最大线程:int.max,活跃时间:10ms,队列:延迟队列(DelayedWorkQueue)。
  4. Executors.newSingleThreadExecutor(),单线程池。核心线程:1,最大线程:1,活跃时间:0s,队列:阻塞队列。
  5. Executors.newWorkStealingPool(),工作窃取线程池,通过ForkJoinPool实现的。

如何合理使用线程池?

使用自定义线程池

new ThreadPoolExecutor(coreThreads, poolSize, 10, TimeUnit.SECONDS, state.threadPoolQueue,
new ThreadPoolExecutor.AbortPolicy());

核心线程数、最大线程数、阻塞队列大小设置

CPU密集型

核心线程数:CPU核数 + 1。

最大线程数:核心线程数的 2 - 3 倍。

队列大小:需要考虑任务的到达速率(任务产生的频率)、任务的执行时间和系统资源。如果系统资源有限或者任务不能长时间等待,可以设置较小的队列。反之任务到达速率较快,可以长时间执行,且系统资源充足,可以设置较大的队列。旺店通任务队列大小100,阻塞队列使用的是ArrayBlockingQueue。

IO密集型

核心线程数:CPU核数 * 2。

最大线程数:核心线程数的 2 - 3 倍。

队列大小:需要考虑任务的到达速率(任务产生的频率)、任务的执行时间和系统资源。如果系统资源有限或者任务不能长时间等待,可以设置较小的队列。反之任务到达速率较快,可以长时间执行,且系统资源充足,可以设置较大的队列。旺店通任务队列大小100,阻塞队列使用的是ArrayBlockingQueue。

http://www.xdnf.cn/news/123859.html

相关文章:

  • Java Collections工具类指南
  • express-generratior工具用法
  • 2025德国FIBO展会:绝影XENJOY以创新科技引领智能健身新浪潮
  • 【华为HCIP | 华为数通工程师】821—多选解析—第十五页
  • 如何找到win11系统powershell的属性
  • Nature Genetics | 测序技术与深度学习在 circRNA 鉴定中的应用
  • 如何在Android中实现低延迟的多实例RTSP|RTMP播放器
  • 论文阅读笔记——π0.5: a Vision-Language-Action Model with Open-World Generalization
  • Linux命令-strace
  • 第13章 身份验证:使用Identity将用户添加到应用程序中
  • 多线程(线程安全)
  • 处理任务“无需等待”:集成RabbitMQ实现异步通信与系统解耦
  • 十分钟应急响应——自定义工具链整合实战
  • 致远oa部署
  • 炼锌废渣提取钴工艺流程
  • Powershell 命令实操
  • PCB 制造流程分步指南
  • 重磅更新!Nature再推出新子刊!(附Nature全目录下载)
  • 三维重建模块VR,3DCursor,MPR与VR的坐标转换
  • 【MongoDB】卸载、安装低版本
  • RabbitMQ 中的队列声明
  • 动态规划dp专题-(下)
  • Ollama工具调用(Tool Calls)业务应用案例
  • 网站高可用架构设计基础——高可用策略和架构原则
  • 实现Variant
  • Ubuntu中选择Python虚拟环境
  • 仿真每日一练 | ABAQUS应力松弛
  • 【Java 数据结构】泛型
  • golang的cgo的一点小心得
  • 智能电网第5期 | 老旧电力设备智能化改造:协议转换与边缘计算