1. 什么是线程池?

线程池就像是一个线程管理工厂,它可以:

  • 预先创建一些线程放在"池子"里

  • 当有任务时,复用这些线程,而不是创建新线程

  • 任务完成后,线程不销毁,等待下一个任务

线程池工作流程(生动形象版)

想象一个银行窗口系统:

任务到来时:
1. 先看"正式窗口"(核心线程)有没有空闲 → 有空就用
2. 如果正式窗口都忙,任务去"等待区"(工作队列)排队
3. 如果等待区也满了,呼叫"临时窗口"(创建新线程直到最大线程数)
4. 如果所有窗口都忙,等待区也满了 → 执行"拒绝策略"
5. 忙完后,临时窗口空闲超过指定时间就关闭

2. 为什么要用线程池?

没有线程池的问题:

// 每次任务都创建新线程
new Thread(() -> {
    // 执行任务
}).start();
  • 频繁创建/销毁线程 → 消耗资源

  • 线程数量不可控 → 可能创建过多线程导致系统崩溃

使用线程池的好处:

  • 资源复用:线程可重复使用

  • 控制并发数:避免线程过多

  • 提高响应速度:线程已创建好,无需等待

  • 统一管理:方便监控和调优

3. 线程池核心组件(类比公司)

组件

类比公司部门

作用

corePoolSize(核心线程数)

正式员工

最少要保持的线程数量

maximumPoolSize(最大线程数)  

总编制(正式+临时)

最多可创建的线程数

workQueue(工作队列) 

待办任务列表

存放等待执行的任务

threadFactory(线程工厂) 

HR部门

线程工厂,用于创建线程

handler(拒绝策略处理器)  

拒绝接待

任务太多时的处理方式

keepAliveTime(存活时间)  

临时工合同期

非核心线程空闲存活时间

4. 创建线程池的简单方式

4.1 Executors工厂类(快捷方式)

// 1. 固定大小的线程池(正式员工固定)
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 2. 单线程线程池(只有1个员工)
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 3. 可缓存的线程池(忙时招人,闲时裁员)
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 4. 定时任务线程池(做计划任务的)
ScheduledExecutorService scheduledPool = 
    Executors.newScheduledThreadPool(3);

4.2 ThreadPoolExecutor(自定义创建)

ThreadPoolExecutor pool = new ThreadPoolExecutor(
    5,     // 核心线程数:最少5个"正式工"
    10,    // 最大线程数:最多10个员工(5正式+5临时)
    60,    // 临时工空闲60秒后解雇
    TimeUnit.SECONDS,  // 时间单位:秒
    new ArrayBlockingQueue<>(100), // 任务队列:最多存100个任务
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);

5. 四种拒绝策略

// 1. 直接抛出异常(默认)
new ThreadPoolExecutor.AbortPolicy();

// 2. 谁提交的任务谁自己执行
new ThreadPoolExecutor.CallerRunsPolicy();

// 3. 丢弃队列中最老的任务
new ThreadPoolExecutor.DiscardOldestPolicy();

// 4. 直接丢弃新任务(静默丢弃)
new ThreadPoolExecutor.DiscardPolicy();

后边会单独写一下不同线程池的使用、工作队列和拒绝策略。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐