线程池总结

1. 线程池是什么

场景:麦当劳/肯德基的点餐取餐流程

传统方式(没有线程池):

  • 每来一个顾客,经理就现招一个临时工,从培训到上岗要5分钟

  • 顾客取完餐,这个临时工立刻被解雇

  • 下一个顾客来,又要重新招聘培训

  • 高峰期时,经理一直在招聘和解雇,手忙脚乱

使用线程池的方式:

  1. 预先准备:经理早上就培训好3个固定员工站在取餐窗口后

  2. 顾客点餐:顾客点完餐拿到号码,在取餐区等待

  3. 分配任务:有空闲窗口时,叫号员喊:"xxx号请到2号窗口"

  4. 高效处理:窗口员工快速配餐,完成后立即服务下一个顾客

  5. 灵活调整

    • 中午人多时,经理临时增加1个窗口(扩大线程池)

    • 下午人少时,让1个员工去休息(缩小线程池)

线程池最大的好处就是减少每次启动、销毁线程的损耗。

2.线程池的核心参数

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

2.1 corePoolSize(核心线程数)

  • 线程池中保持存活的最小线程数量

  • 即使这些线程处于空闲状态也不会被销毁

  • 除非设置allowCoreThreadTimeOut为true

2.2 maximumPoolSize(最大线程数)

  • 线程池允许创建的最大线程数量

  • 当工作队列满时,线程池会创建新线程,直到达到此限制

2.3 keepAliveTime(线程存活时间)

  • 非核心线程的空闲存活时间

  • 超过此时间,空闲的非核心线程将被终止

2.4 workQueue(工作队列)

  • 用于存放等待执行的任务的阻塞队列

  • 常见类型:

    • LinkedBlockingQueue:无界队列(默认)

    • ArrayBlockingQueue:有界队列

    • SynchronousQueue:不存储元素的队列

    • PriorityBlockingQueue:优先级队列

2.5 ThreadFactory(线程工厂)

  • 用于创建新线程的工厂

  • 可以自定义线程名称、优先级、守护状态等

2.6 RejectedExecutionHandler(拒绝策略)

  • 当线程池和工作队列都满时,对新任务的处理策略

  • 四种内置策略:

    • AbortPolicy(默认):抛出RejectedExecutionException异常

    • CallerRunsPolicy:由调用线程执行该任务

    • DiscardPolicy:直接丢弃任务

    • DiscardOldestPolicy:丢弃队列中最旧的任务,然后重试

3. Executors 创建线程池的几种方式

  • newFixedThreadPool: 创建固定线程数的线程池
java 复制代码
//创建固定大小为5的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 特点:
// - 核心线程数 = 最大线程数 = 指定参数
// - 使用无界LinkedBlockingQueue
// - 适用于负载较重的服务器,限制线程数量
  • newCachedThreadPool: 创建线程数目动态增长的线程池.
java 复制代码
//创建可缓存的线程池
    ExecutorService cashedThreadPool = Executors.newCachedThreadPool();
    // 特点:
    // - 核心线程数 = 0,最大线程数 = Integer.MAX_VALUE
    // - 使用SynchronousQueue(不存储元素)
    // - 空闲线程60秒后终止
    // - 适用于执行大量短期异步任务
  • newSingleThreadExecutor: 创建只包含单个线程的线程池.
java 复制代码
//创建单线程的线程池
    ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
    // 特点:
    // - 只有一个工作线程
    // - 保证任务顺序执行
    // - 适用于需要顺序执行任务的场景
    // - 使用无界LinkedBlockingQueue
    //"无界"的具体表现:
    // 1. 默认构造函数:Integer.MAX_VALUE 容量(约21亿)
    // 2. 可指定初始容量,但超过后会继续接受新元素
    // 3. 实际上受JVM堆内存限制
  • newScheduledThreadPool: 设定 延迟时间后执行命令,或者定期执行命令. 是进阶版的 Timer.
java 复制代码
//创建可定时执行的线程池
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
        // 常用方法:
        // 延迟执行
        scheduledThreadPool.schedule(task,10, TimeUnit.SECONDS);
        /*
         1."task":要执行的任务
         2."10":延迟时间
         3."TimeUnit.SECONDS":时间单位,秒
         */
        //固定频率执行
        scheduledThreadPool.scheduleAtFixedRate(task,5,2,TimeUnit.SECONDS);
        /*
         1."task":要执行的任务
         2."5":初始延迟时间,即从现在开始等待5秒后,第一次执行任务
         3."2":任务执行的周期,即每隔2秒执行一次任务
         4."TimeUnit.SECONDS":时间单位,秒
         */
        //固定延迟执行
        scheduledThreadPool.scheduleWithFixedDelay(task,5,2,TimeUnit.SECONDS);
        /*
         1."task":要执行的任务
         2."5":初始延迟时间,即从现在开始等待5秒后,第一次执行任务
         3."2":任务执行结束到下一次任务开始之间的延迟时间,即每次任务完成后,等待2秒再开始下一次
         4."TimeUnit.SECONDS":时间单位,秒
         */    

Executors 本质上是 ThreadPoolExecutor 类的封装.

相关推荐
飘若随风2 小时前
JS学习系列-01-什么是JS
开发语言·javascript·学习
定偶2 小时前
网络编程总结
开发语言·网络·数据结构·网络编程
w_t_y_y2 小时前
工具Cursor(三)MCP(3)常用的三方MCP Tools
java
claem2 小时前
Mac端 Python脚本创建与理解
开发语言·python·macos
CoderCodingNo2 小时前
【GESP】C++五级练习题 luogu-B3628 机器猫斗恶龙
开发语言·c++·算法
what丶k2 小时前
你应该更新的 Java 知识:Record 特性深度解析
java·开发语言
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 剧本杀服务管理系统的设计与实现为例,包含答辩的问题和答案
java
乐观勇敢坚强的老彭2 小时前
c++信奥寒假营集训01
android·java·c++
mango_mangojuice2 小时前
C++ 学习笔记(string类)
开发语言·c++·笔记·学习