题目
使用Java线程池执行多个任务
信息
- 类型:问答
- 难度:⭐
考点
线程池创建,任务提交,线程池关闭
快速回答
使用线程池执行任务的步骤:
- 通过
Executors.newFixedThreadPool()创建固定大小线程池 - 使用
execute()方法提交Runnable任务 - 任务执行完成后调用
shutdown()关闭线程池
关键注意事项:
- 避免使用
new Thread()直接创建线程 - 务必在程序结束时关闭线程池
- 使用
Runnable接口定义任务逻辑
1. 线程池基础原理
线程池通过复用线程减少创建/销毁开销,核心组件包括:
- 工作队列:存放待执行任务(
BlockingQueue) - 线程集合:执行任务的线程(
HashSet<Worker>) - 线程工厂:创建新线程(
ThreadFactory)
2. 代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 1. 创建固定大小为3的线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 2. 提交10个任务
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("执行任务: " + taskId + ", 线程: " + Thread.currentThread().getName());
});
}
// 3. 关闭线程池(非强制,等待任务完成)
executor.shutdown();
}
}3. 最佳实践
- 线程池类型选择:
newFixedThreadPool:固定线程数(适合稳定负载)newCachedThreadPool:弹性线程数(适合短期异步任务)
- 关闭顺序:
shutdown():温和关闭(执行完已提交任务)shutdownNow():强制关闭(返回未执行任务列表)
- 任务定义:优先实现
Runnable接口而非Callable
4. 常见错误
| 错误 | 后果 | 解决方案 |
|---|---|---|
| 忘记关闭线程池 | 线程泄漏,JVM无法退出 | 使用try-finally确保关闭 |
使用new Thread() | 资源耗尽(如创建上千线程) | 始终使用线程池管理 |
| 捕获任务异常不当 | 异常被吞没难以排查 | 在任务内部添加try-catch |
5. 扩展知识
- 线程池参数:核心线程数、最大线程数、存活时间、队列类型
- 拒绝策略:当队列满时的处理机制(如
AbortPolicy抛出异常) - 监控:通过
ThreadPoolExecutor的getActiveCount()等方法监控状态
6. 完整执行流程
- 主线程创建线程池(3个工作线程)
- 10个任务进入工作队列
- 工作线程从队列获取任务执行
- 输出显示线程复用(如"pool-1-thread-1"执行多个任务)
shutdown()调用后不再接受新任务- 所有任务完成后线程池终止