返回

彻底弄懂ThreadPoolExecutor线程池核心原理,面试官惊叹你的专业!

后端

ThreadPoolExecutor 线程池:深度解析执行流程和关键机制

在 Java 并发编程中,ThreadPoolExecutor 线程池是一个重要的组件,它负责管理线程池中的工作线程,以高效地执行任务。本文将深入探究 ThreadPoolExecutor 的执行流程,了解它如何回收非核心线程、维护核心线程,以及它在拒绝策略方面的运作方式。

线程池执行流程

当我们提交一个任务时,它会进入线程池的任务队列中。当工作线程空闲时,它会从队列中获取任务并执行它。一旦任务完成或出现异常,工作线程就会将结果或异常信息返回给调用者。

回收非核心线程

非核心线程会在以下几种情况下被回收:

  • 存活时间策略: 如果非核心线程空闲时间超过一定时间,它会被回收。
  • 核心线程数策略: 当核心线程数发生变化时,非核心线程可能会被回收,以匹配实际需求。
  • 任务队列长度策略: 当任务队列长度超过一定阈值时,非核心线程可能会被回收,以防止任务队列过长。

维护核心线程

核心线程会在以下几种情况下被维护:

  • 始终保持核心线程数: 无论任务数量如何变化,核心线程数始终保持不变。
  • 按需创建核心线程: 当任务数量增加时,会创建新的核心线程来处理任务。
  • 回收空闲核心线程: 当核心线程空闲时间超过一定时间后,可能会被回收。

拒绝策略

当线程池中的任务数量超过线程池的容量时,ThreadPoolExecutor 线程池会根据拒绝策略来处理新提交的任务。拒绝策略有四种:

  • 抛出异常: 当线程池达到容量时,会抛出 RejectedExecutionException 异常。
  • 丢弃任务: 当线程池达到容量时,会丢弃新提交的任务。
  • 调用者运行: 当线程池达到容量时,由调用者自己执行新提交的任务。
  • 饱和策略: 当线程池达到容量时,等待任务队列中有空闲位置再执行新提交的任务。

代码示例

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadPoolExecutorExample {

    public static void main(String[] args) {
        // 创建一个线程池,核心线程数为 2,最大线程数为 4,任务队列大小为 10
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2, 4, 10);

        // 提交 10 个任务到线程池
        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(() -> {
                System.out.println("任务 " + Thread.currentThread().getName() + " 正在执行");
            });
        }

        // 查看线程池的状态
        System.out.println("核心线程数:" + threadPoolExecutor.getCorePoolSize());
        System.out.println("最大线程数:" + threadPoolExecutor.getMaximumPoolSize());
        System.out.println("任务队列大小:" + threadPoolExecutor.getQueue().size());
    }
}

常见问题解答

  1. 什么是核心线程和非核心线程?

    • 核心线程在任何情况下都不会被回收,而非核心线程会在任务减少时被回收。
  2. ThreadPoolExecutor 的拒绝策略是什么?

    • ThreadPoolExecutor 提供四种拒绝策略:抛出异常、丢弃任务、调用者运行和饱和策略。
  3. 如何配置 ThreadPoolExecutor 的线程池参数?

    • 使用 ThreadPoolExecutor 的构造函数或 setCorePoolSize()setMaxPoolSize()setQueueCapacity() 方法配置线程池参数。
  4. 什么时候应该使用 ThreadPoolExecutor

    • 当你需要管理线程池并优化并发性能时,可以使用 ThreadPoolExecutor
  5. 如何监控 ThreadPoolExecutor 的性能?

    • 使用 ThreadPoolExecutorgetCompletedTaskCount()getPoolSize()getQueueSize() 等方法监控线程池的性能。