线程池原理及其常用线程池

线程池原理与类型详解

一、线程池核心原理

  1. 为什么需要线程池

• 降低资源消耗:减少线程创建和销毁的开销

• 提高响应速度:任务到达时,线程已存在,直接执行

• 统一管理:控制并发数量,避免系统崩溃

• 提供功能:支持定时、延迟、周期执行

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

新任务提交

  1. 核心线程是否已满? ──否──→ 创建核心线程执行
    ↓是
  2. 工作队列是否已满? ──否──→ 任务入队等待
    ↓是
  3. 线程数是否达到最大? ──否──→ 创建非核心线程执行
    ↓是
  4. 执行拒绝策略

二、Java 内置线程池类型

  1. FixedThreadPool(固定大小)
bash 复制代码
ExecutorService executor = Executors.newFixedThreadPool(5);

特点:

• 固定数量的核心线程

• 无界队列(LinkedBlockingQueue)

• 线程永不回收

• 适用:负载较重的服务器,需要限制线程数

  1. CachedThreadPool(缓存线程池)
bash 复制代码
ExecutorService executor = Executors.newCachedThreadPool();

特点:

• 核心线程数 = 0,最大线程数 = Integer.MAX_VALUE

• 使用 SynchronousQueue(不存储元素)

• 空闲线程60秒后回收

• 适用:执行大量短期异步任务

  1. SingleThreadExecutor(单线程)
bash 复制代码
ExecutorService executor = Executors.newSingleThreadExecutor();

特点:

• 只有一个线程

• 无界队列

• 保证任务顺序执行

• 适用:需要顺序执行的任务

  1. ScheduledThreadPool(定时线程池)
bash 复制代码
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);

特点:

• 支持定时、周期性执行

• 核心线程可回收

• 适用:定时任务、延时任务

  1. WorkStealingPool(工作窃取,Java 8+)
bash 复制代码
ExecutorService executor = Executors.newWorkStealingPool();

特点:

• 基于 ForkJoinPool

• 使用工作窃取算法

• 并行处理任务

• 适用:计算密集型任务

三、线程池状态

bash 复制代码
// ThreadPoolExecutor 中的状态定义
private static final int RUNNING    = -1 << COUNT_BITS;  // 运行中
private static final int SHUTDOWN   =  0 << COUNT_BITS;  // 关闭中(不接受新任务)
private static final int STOP       =  1 << COUNT_BITS;  // 停止(不处理队列任务)
private static final int TIDYING    =  2 << COUNT_BITS;  // 整理中
private static final int TERMINATED =  3 << COUNT_BITS;  // 终止

四、拒绝策略

  1. AbortPolicy(默认)
bash 复制代码
// 抛出 RejectedExecutionException
new ThreadPoolExecutor.AbortPolicy()
  1. CallerRunsPolicy
bash 复制代码
// 由调用线程执行任务
new ThreadPoolExecutor.CallerRunsPolicy()
  1. DiscardPolicy
bash 复制代码
// 直接丢弃任务,不抛异常
new ThreadPoolExecutor.DiscardPolicy()
  1. DiscardOldestPolicy
bash 复制代码
// 丢弃队列中最旧的任务,然后重试
new ThreadPoolExecutor.DiscardOldestPolicy()

五、自定义线程池示例

bash 复制代码
// 生产环境推荐自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5,                                      // 核心线程数
    10,                                     // 最大线程数
    60L, TimeUnit.SECONDS,                  // 空闲时间
    new ArrayBlockingQueue<>(100),          // 有界队列(防止内存溢出)
    new ThreadFactory() {                   // 自定义线程工厂
        private final AtomicInteger count = new AtomicInteger(1);
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "my-thread-" + count.getAndIncrement());
        }
    },
    new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
);

六、线程池监控

bash 复制代码
ThreadPoolExecutor executor = ...;

// 监控指标
executor.getPoolSize();          // 当前线程数
executor.getActiveCount();       // 活动线程数
executor.getQueue().size();      // 队列大小
executor.getCompletedTaskCount();// 完成任务数
executor.getTaskCount();         // 总任务数

七、最佳实践

  1. 设置合理的拒绝策略

// 根据业务需求选择

bash 复制代码
new ThreadPoolExecutor.CallerRunsPolicy()  // 重要任务,不能丢弃
new ThreadPoolExecutor.AbortPolicy()       // 快速失败,便于排查
  1. 正确关闭线程池
bash 复制代码
executor.shutdown();                    // 温和关闭
executor.shutdownNow();                 // 立即关闭
executor.awaitTermination(10, TimeUnit.SECONDS);  // 等待关闭
  1. 线程泄漏问题
bash 复制代码
// 使用 submit() - 异常被吞没
executor.submit(() -> {
    try {
        // 任务逻辑
    } catch (Exception e) {
        // 必须捕获异常,否则线程会退出,控制台没有任何异常输出!程序继续运行,就像什么都没发生
        log.error("任务执行异常", e);
    }
});

// 使用 execute() - 异常能抛出
executor.execute(() -> {
    int result = 1 / 0;  // ❌ 异常能抛出到控制台
});

总结

线程池是 Java 并发编程的核心组件,合理使用线程池可以:

  1. 提高系统性能
  2. 控制资源消耗
  3. 提供统一管理
  4. 增强系统稳定性

根据业务场景选择合适的线程池类型和参数配置是关键。

相关推荐
lbb 小魔仙2 小时前
【Java】基于 Java 的分布式系统实战:分布式锁 + 事务 + 一致性算法,干货满满
java·分布式·算法
葡萄成熟时 !2 小时前
JavaAPI 工具类
java
sunnyday04262 小时前
Spring Boot 中的优雅重试机制:从理论到实践的完整指南
java·spring boot·后端
Ethan-D2 小时前
每日一题#21 二维 DP + 计数类
java·python·算法·leetcode·动态规划
虫小宝2 小时前
企业微信官方API与自建机器人系统的鉴权体系对比及Java集成方案
java·机器人·企业微信
运维行者_2 小时前
Applications Manager 引入持续剖析技术,突破传统 APM 监控瓶颈
java·运维·网络·jvm·数据库·安全·web安全
biyezuopinvip2 小时前
基于JavaSSM+MySQL的机房预约管理系统设计与实现
java·mysql·毕业设计·论文·ssm·jsp·机房预约管理系统设计与实现
开开心心_Every2 小时前
免费视频画质增强:智能超分辨率无损放大
java·服务器·前端·python·学习·edge·powerpoint
lbb 小魔仙2 小时前
【Java】Java 实战项目:从零开发一个在线教育平台,附完整部署教程
java·开发语言