三分钟掌握Java线程池核心用法

三分钟掌握Java面试线程池核心用法

一、为什么需要线程池?

// 传统线程创建方式的问题
new Thread(() -> {
    // 业务逻辑
}).start();
  • ❌ 频繁创建/销毁线程消耗资源
  • ❌ 无法控制并发数量
  • ❌ 缺乏统一管理机制

二、ThreadPoolExecutor核心参数(7个)

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,   // 核心线程数(常驻员工)
    maximumPoolSize,// 最大线程数(临时工+常驻)
    keepAliveTime,  // 空闲线程存活时间
    TimeUnit.SECONDS,// 时间单位
    workQueue,      // 任务队列(候客区)
    threadFactory,  // 线程创建工厂
    handler         // 拒绝策略(客满处理)
);

三、工作流程图解

[任务提交] → 核心线程?→ 队列未满?→ 创建临时线程?→ 执行拒绝策略
           ↓          ↓             ↓
          立即执行 → 进入队列 → 扩容线程池

四、快速上手示例

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 创建线程池(建议使用工厂方法)
        ExecutorService pool = Executors.newFixedThreadPool(3);
        
        // 提交10个任务
        for (int i = 0; i < 10; i++) {
            pool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "执行任务");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        // 优雅关闭
        pool.shutdown();
    }
}

五、关键注意事项

  1. 线程数量公式
    CPU密集型:核心数 + 1
    IO密集型:核心数 * 2

  2. 四种拒绝策略

    • AbortPolicy(默认抛出异常)
    • CallerRunsPolicy(回调给提交线程)
    • DiscardPolicy(静默丢弃)
    • DiscardOldestPolicy(丢弃队列最老任务)
  3. 常见坑点

    • 忘记关闭线程池 → 内存泄漏
    • 使用无界队列 → OOM风险
    • 错误估算线程数量 → 资源浪费

六、最佳实践建议

  1. 使用ThreadPoolExecutor构造函数而非Executors工厂方法
  2. 为线程设置有意义的名字(通过ThreadFactory)
  3. 监控线程池状态(通过getActiveCount()等方法)

配套练习建议:

  1. 调整核心/最大线程数观察任务执行顺序
  2. 尝试不同拒绝策略触发场景
  3. 使用SynchronousQueue实现直接传递
posted @ 2025-03-04 23:55  皮皮是个不挑食的好孩子  阅读(33)  评论(0)    收藏  举报