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

线程池原理与类型详解

一、线程池核心原理

  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. 增强系统稳定性

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

相关推荐
追逐梦想的张小年5 小时前
JUC编程04
java·idea
好家伙VCC5 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
南极星10056 小时前
蓝桥杯JAVA--启蒙之路(十)class版本 模块
java·开发语言
消失的旧时光-19436 小时前
第十三课:权限系统如何设计?——RBAC 与 Spring Security 架构
java·架构·spring security·rbac
不能隔夜的咖喱6 小时前
牛客网刷题(2)
java·开发语言·算法
serve the people6 小时前
python环境搭建 (十二) pydantic和pydantic-settings类型验证与解析
java·网络·python
lekami_兰6 小时前
Java 并发工具类详解:4 大核心工具 + 实战场景,告别 synchronized
java·并发工具
有位神秘人6 小时前
Android中Notification的使用详解
android·java·javascript
tb_first7 小时前
LangChain4j简单入门
java·spring boot·langchain4j
独自破碎E8 小时前
【BISHI9】田忌赛马
android·java·开发语言