本文参考B站技术视频 《Java手写线程池实战》 的核心思路实现,结合代码解析线程池设计思想
在多线程编程中,频繁创建/销毁线程会产生大量性能开销。线程池通过✨ 线程复用 和 任务队列管理 机制,实现了:
public class MyThreadPool {
private final int corePoolSize; // 核心线程数
private final int maxSize; // 最大线程数
private final int timeout; // ⏳ 非核心线程空闲超时
private final TimeUnit timeUnit; // ⏰ 时间单位
private final BlockingQueue<Runnable> blockingQueue; // 任务队列
private final RejectHandle rejectHandle; // 拒绝策略
}
参数 | 作用说明 |
---|---|
corePoolSize | 长期存活的线程数量,即使处于空闲状态 |
maxSize | 允许创建的最大线程数 |
timeout | 非核心线程空闲等待时间(超时后自动销毁) |
blockingQueue | 任务缓存队列(推荐使用有界队列) |
rejectHandle | 队列满时的拒绝策略 |
class CoreThread extends Thread {
@Override
public void run() {
while (true) { // ♻️ 永久运行
try {
Runnable task = blockingQueue.take();
task.run(); // ♂️立即执行任务
} catch (InterruptedException e) {
// ⚠️处理中断异常
}
}
}
}
// 直接丢弃策略实现
public class DiscardRejectHandle implements RejectHandle {
@Override
public void reject(Runnable command, MyThreadPool threadPool) {
System.out.println("❌ 任务被丢弃: " + command);
}
}
其他常见拒绝策略:
public static void main(String[] args) {
MyThreadPool pool = new MyThreadPool(3, 5, 1, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2), new DiscardRejectHandle());
for (int i = 0; i < 8; i++) {
int taskId = i;
pool.execute(() -> {
try {
Thread.sleep(1000); // 模拟任务执行
System.out.println(Thread.currentThread().getName()
+ " ✅ 执行任务-" + taskId);
} catch (InterruptedException e) {
e.printStackTrace(); // ⚠️异常处理
}
});
}
}
执行结果特征:
特性 | 手写线程池 | ThreadPoolExecutor |
---|---|---|
线程分类 | 核心/临时线程 | 核心/非核心线程 |
队列策略 | 必须显式指定 | 支持多种队列类型 |
拒绝策略 | 需自定义实现 | 内置4种标准策略 |
线程回收 | 简单超时机制 | 支持灵活配置 |
状态管理 | 未实现 | 完整生命周期管理(RUNNING/SHUTDOWN等) |
原理深入讲解推荐观看:《Java手写线程池实战》
通过手写线程池,不仅可以深入理解线程池的工作原理,还能根据实际业务需求进行定制化扩展。建议读者结合JDK原生线程池源码进行对比学习,收获会更大!