JAVA并发编程
7. 线程池
7.1 概念
7.1.1 无限制创建线程的缺点
- 线程生命周期的开销(创建和关闭线程等开销)
- 活动线程消耗系统资源,大量空闲线程占用更多内存,给垃圾回收器带来压力。
- 过多的线程会影响稳定性,甚至拖垮程序。
7.1.2 简单过程和优点
过程:线程池管理一个工作者线程的同构池,并与工作队列绑定。它从工作队列中获取下一个任务并执行。
优点:
-
可以重用线程,减少创建和关闭线程的开销。
-
提高响应性,不需要创建线程也就不会延迟任务的执行。
-
通过调整线程池大小,可以保持处理器忙碌的同时防止过多线程竞争资源(耗尽内存)。
7.1.3 线程池的大小
-
对于计算密集型任务,线程数为CPU+1。
-
包含I/O等阻塞操作可以加大线程池。
-
计算公式:No(threads) = No(CPU)*U(cpu)*(1+W/C)
No表示数量,U表述利用率,W/C为等待时间域计算时间的比率
7.1.4 线程池死锁
- 线程池中一个任务依赖于其他任务的执行,就可能产生死锁。
- 解决:给同一线程池提交相互独立的任务,而不是彼此依赖的任务。
7.2 Executor框架
7.2.1 作用
- 支持不同类型的任务执行策略
- 为任务提交和任务执行之间的解耦提供了标准方法
- 提供对生命周期的支持以及钩子函数
- 可以添加统计收集、应用程序管理机制和监视器等扩展
- 基于生产者-消费者模式
7.2.2 Executor接口
-
唯一方法
方法名 返回值 描述 execute(Runnable) void 在将来的某个时间执行给定的命令
7.2.3 ExecutorService接口
-
继承Executor接口,添加了用于生命周期管理的方法
-
提供了三种生命周期状态:运行、关闭、终止
-
部分方法
方法名 返回值 描述 submit(Runnable) Future<?> 提交一个可运行的任务执行,并返回一个表示该任务的未来。 shutDown() void 平缓关闭:停止接受新任务,等待已提交任务完成 shutDownNow() List<Runnable> 强制关闭:尝试取消所有任务,返回等待的任务列表 isShutDown() boolean 判断是否关闭 isTerminated() boolean 所有任务完成会进入终止状态 awaitTermination(long, TimeUnit) boolean 等待进入终止状态,返回一段时间后是否关闭。通常后接shutdown -
实现类:ThreadPoolExecutor
7.2.4 ScheduledExecutorService接口
-
继承ExecutorService接口
-
作用:调度命令在给定的时间后或定期执行
-
Timer:Timer只创建唯一的线程执行所有任务&