线程池总结

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 小时前
QT第6个程序 - 网页内容摘取
开发语言·qt
darkb1rd2 小时前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
南极企鹅2 小时前
springBoot项目有几个端口
java·spring boot·后端
历程里程碑2 小时前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
郝学胜-神的一滴2 小时前
深入浅出:使用Linux系统函数构建高性能TCP服务器
linux·服务器·开发语言·网络·c++·tcp/ip·程序人生
清风拂山岗 明月照大江2 小时前
Redis笔记汇总
java·redis·缓存
承渊政道2 小时前
Linux系统学习【Linux系统的进度条实现、版本控制器git和调试器gdb介绍】
linux·开发语言·笔记·git·学习·gitee
xiaoxue..3 小时前
合并两个升序链表 与 合并k个升序链表
java·javascript·数据结构·链表·面试
JQLvopkk3 小时前
C# 轻量级工业温湿度监控系统(含数据库与源码)
开发语言·数据库·c#
忧郁的Mr.Li3 小时前
SpringBoot中实现多数据源配置
java·spring boot·后端