3、线程池:别再只会 Executors.newFixedThreadPool() 了!

171 阅读2分钟

今天我们来聊一个经典却容易被滥用的工具:线程池(ThreadPoolExecutor)

很多人写代码就是一把梭:

ExecutorService executor = Executors.newFixedThreadPool(10);

这样用当然简单,但——
面试官:你知道它底层怎么实现的吗?你知道什么时候该用自定义线程池吗?


1️⃣ 线程池的核心概念

线程池主要靠 ThreadPoolExecutor 这个类实现。它有几个核心参数:
✅ corePoolSize(核心线程数)
✅ maximumPoolSize(最大线程数)
✅ keepAliveTime(空闲线程存活时间)
✅ workQueue(任务队列)
✅ threadFactory(线程工厂)
✅ handler(拒绝策略)

简单来说:

  • 核心线程 + 队列处理任务
  • 队列满了才用非核心线程
  • 都满了才触发拒绝策略

image.png


2️⃣ Executors 系列的坑

newFixedThreadPool() → 核心线程固定,队列是无界的,任务太多可能撑爆内存
newCachedThreadPool() → 没有限制,瞬间大量并发可能把 CPU 打死
newSingleThreadExecutor() → 单线程,适合串行化任务,不适合高并发

建议生产代码用:

new ThreadPoolExecutor(...) 自定义线程池


3️⃣ 自定义线程池怎么配?

实战配置示例:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    10,                  // 核心线程数
    20,                  // 最大线程数
    60, TimeUnit.SECONDS,// 空闲线程存活时间
    new ArrayBlockingQueue<>(100),  // 队列容量
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略
);

常用拒绝策略:
✅ AbortPolicy → 抛异常(默认)
✅ CallerRunsPolicy → 谁提交谁自己跑
✅ DiscardPolicy → 直接丢弃
✅ DiscardOldestPolicy → 丢掉最老的任务


4️⃣ 小幽默:线程池的“过劳死”

我见过有人在循环里 newFixedThreadPool,每次都 new 一个线程池,结果服务器直接炸了……
线程池:兄弟,咱也是有生命的,别无限造我啊!


5️⃣ 总结

✅ Executors 工厂类方便,但不适合生产
✅ 要搞清楚线程池参数配置和队列类型
✅ 自定义 ThreadPoolExecutor 是高级 Java 工程师的基本功
✅ 多线程不是万能的,搞错了只会让系统更慢、更脆弱