ThreadPoolExecutor 基础入门

本文深入分析了JDK 1.8中ThreadPoolExecutor的实现,探讨了线程池的核心优势和执行流程。针对不同类型的内置线程池可能带来的问题,如可能导致的OOM风险,提出了自定义线程池的需求。文章还介绍了如何根据业务需求调整线程池参数,并列举了线程池的重要管理方法,帮助读者更好地理解和监控线程池的运行状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文基于版本为 1.8.0_281 的 JDK 对 ThreadPoolExecutor 的源码进行分析
在这里插入图片描述
不知道比较新的 JDK 内 ThreadPoolExecutor 内实现咋样的,应该大差不差吧,研究好主流的 JDK 1.8 一通百通。

全局概览

先来说下使用线程池的好处:

  1. 核心线程可以复用,省去创建线程的开销
  2. 通过合理的参数控制线程的数量,可以防止服务器资源消耗过多
  3. 提供了大量统计相关的方法,方便对线程池进行管理

再来说下大概的流程:

  1. 线程总数量 < corePoolSize,总会创建一个新的核心线程执行任务
  2. 线程总数量 >= corePoolSize 时,新来的线程任务进入任务队列中等待,然后空闲的核心线程去队列中取任务执行
  3. 当队列满了后,再来新的任务时启动非核心线程去执行任务
  4. 队列也满了,总线程数达到 maximumPoolSize,采取聚集策略进行处理

ThreadPoolExecutor 源码分析

构造方法

TODO

使用

自定义线程池

先来说下为什么要自定义线程池?

一种情况是自带那几种线程池的有问题,具体有哪些问题呢?下面我们一个一个来说:

  1. CachedThreadPool:创建了一个「最大线程数为 Integer.MAX_VULUE 」的线程池,如果线程任务耗时并且大量创建,会导致 OOM;
  2. FixedThreadPool:创建了一个固定大小可重复的线程池,队列是 LinkedBlockingQueue 无界阻塞队列(因为其默认大小是 Integer.MAX_VALUE),随着任务越来越多,队列中的任务也越来越多,可能会导致 OOM;
  3. SingleThreadExecutor:创建了一个只有一个线程的线程池,队列是 LinkedBlockingQueue 无界阻塞队列(因为其默认大小是 Integer.MAX_VALUE),随着任务越来越多,队列中的任务也越来越多,可能会耗尽 CPU 和内存资源;
  4. ScheduledThreadPool:创建了一个能够定时执行任务或者在给定延迟后执行任务的线程池,最大线程数是 Integer.MAX_VULUE ,队列用了 DelayQueue,也是个无界的,如果使用不恰当,也会 OOM。

一种情况是给定的虽然在自己的业务场景下不会出问题,但是不满足我们的使用,需要我们进行自定义:

  1. 我们可以通过实现 RegectedExecutionHandler 接口来自定义策略;
  2. 对线程池中的线程设置更有标识作用的名字。

结合 Spring

TODO

管理方法

有了下述方法后,就可以直接使用相应的方法对线程池进行监控,当然也可以重新写一个自己的监控类 extends ThreadPoolExecutor,对某些方法的执行前后进行监控(比如启动、执行、关闭)。

核心线程

  • getCorePoolSize():获取核心线程数
  • setCorePoolSize():重新设置线程池的核心线程数
  • prestartCoreThread():预启动一个核心线程,当且仅当工作线程数量小于核心线程数量
  • prestartAllCoreThreads():预启动所有核心线程

线程池容量

  • getMaximumPoolSize():获取线程池容量
  • setMaximumPoolSize():重新设置线程池的最大容量

线程存活

  • setKeepAliveTime():设置空闲工作线程的存活周期
  • getKeepAliveTime():获取空闲工作线程的存活周期

线程队列

  • purge():移除任务队列中所有是Future类型并且已经处于Cancelled状态的任务
  • remove():从任务队列中移除指定的任务
  • BlockingQueue getQueue():获取任务队列的引用

其他

  • getTaskCount():获取所有已经被执行的任务总数的近似值
  • getCompletedTaskCount():获取所有已经执行完成的任务总数的近似值
  • getLargestPoolSize():获取线程池的峰值线程数(最大池容量)
  • getActiveCount():获取所有活跃线程总数(正在执行任务的工作线程)的近似值
  • getPoolSize():获取工作线程集合的容量(当前线程池中的总工作线程数)

关联阅读

线程池运行源码分析

ThreadPoolExecutor 关闭源码分析

推荐阅读

Java线程池实现原理及其在美团业务中的实践

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值