Java线程池原理概述
Java线程池详解
一、使用方式
- 创建线程池
// 使用Executors工厂类
ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 固定大小线程池
ExecutorService cachedPool = Executors.newCachedThreadPool(); // 弹性线程池
ExecutorService scheduledPool = Executors.newScheduledThreadPool(3); // 定时任务线程池// 手动配置(推荐)
ThreadPoolExecutor customPool = new ThreadPoolExecutor(4, // 核心线程数10, // 最大线程数60, // 空闲线程存活时间(秒)TimeUnit.SECONDS, // 时间单位new ArrayBlockingQueue<>(100) // 任务队列
);
- 提交任务
// 执行无返回值任务
executor.execute(() -> {System.out.println("Task running in: " + Thread.currentThread().getName());
});// 提交有返回值任务
Future<String> future = executor.submit(() -> {return "Result from " + Thread.currentThread().getName();
});
System.out.println(future.get()); // 获取结果
- 关闭线程池
executor.shutdown(); // 平缓关闭(执行完队列任务)
executor.shutdownNow(); // 立即关闭(尝试中断所有线程)
二、底层原理
核心组件
- 工作队列:存储待执行任务(阻塞队列实现)
- 工作线程集合:
HashSet<Worker>
- 线程工厂:
ThreadFactory
创建新线程 - 拒绝策略:当队列满时的处理机制
任务执行流程
graph TD A[提交任务] --> B{核心线程空闲?} B -->|是| C[立即执行] B -->|否| D{队列未满?} D -->|是| E[加入队列] D -->|否| F{可创建新线程?} F -->|是| G[创建新线程执行] F -->|否| H[触发拒绝策略]
线程生命周期管理
- 核心线程常驻(除非设置
allowCoreThreadTimeOut
) - 非核心线程超时销毁
- 线程通过
Worker
封装实现任务循环:
while (task != null || (task = getTask()) != null) {task.run(); // 实际执行任务 }
- 核心线程常驻(除非设置
三、自定义线程使用
- 自定义线程工厂
class CustomThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "custom-pool-" + poolNumber.getAndIncrement() + "-thread");}
}// 使用自定义工厂
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 10, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(),new CustomThreadFactory() // 注入工厂
);
- 自定义拒绝策略
class CustomRejectPolicy implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {// 自定义处理逻辑(如记录日志/存入数据库)System.err.println("Task rejected: " + r.toString());}
}// 配置拒绝策略
executor.setRejectedExecutionHandler(new CustomRejectPolicy());
- 扩展线程池行为
class MonitoringThreadPool extends ThreadPoolExecutor {// 重写钩子方法@Overrideprotected void beforeExecute(Thread t, Runnable r) {System.out.println("Start: " + r);}@Overrideprotected void afterExecute(Runnable r, Throwable t) {System.out.println("Finish: " + r);}
}
最佳实践建议
- 避免使用
Executors.newFixedThreadPool()
可能引发OOM(默认使用无界队列) - 合理配置参数:
- CPU密集型:核心线程数 ≈ CPU核数
- IO密集型:核心线程数 ≈ CPU核数 * 2
- 使用
ThreadPoolExecutor
而非ExecutorService
接口以便访问扩展方法 - 重要任务建议使用有界队列+自定义拒绝策略