《Java并发编程实战》-7

线程池的使用

8.1 在任务与执行策略之间的隐形耦合

并非所有的任务有些任务需要明确地指明执行策略,包括:

  • 依赖性任务
  • 使用线程封闭机制的任务。
  • 对应时间敏感的任务。
  • 使用ThreadLocal的任务

在一些任务中,需要拥有或排除某种特定的执行策略。如果某些任务依赖于其他的任务,那么会要求线程池足够大,从而确保它们依赖任务不会被放入等待队列中或者被拒绝,而采用线程封闭机制的任务需要串行执行。通过将这些需求写入文档,将来的代码维护人员就不会由于使用了某种不合适的执行策略而破坏安全性或活跃性。

8.1.1 线程饥饿死锁

每当提交了一个有依赖性的Executor任务时,要清楚地知道可能会出现线程“饥饿”死锁,因此需要在代码或配置Executor的配置文件中记录线程池的大小限制或配置限制。

8.1.2 运行时间较长的任务

如果任务阻塞的时间过长,那么即使不出现死锁,线程池的响应性也会变得糟糕。

定任务等待资源得时间,而不是无限制地等待可以缓解执行时间较长得任务造成的影响。

8.2 设置线程池得大小

一般情况下正确地设置线程池的大小(假设有n个CPU):

  • 计算密集型: 2n+1
  • I/O密集型:2n

8.3 配置ThreadPoolExecutor

线程的创建与销毁

管理队列任务

8.3.3 饱和策略

8.3.4 线程工厂

8.4 扩展ThreadPoolExecutor

实例:给线程池添加统计信息

8.5 递归算法的并行化

实例:谜题框架

对于并发执行的任务,EXecutor框架是一种强大且灵活的框架。它提供了大量可调节的选项,例如创建线程和关闭线程的策略,处理队列任务的策略,处理过多任务的策略,并且提供了几个钩子方法来扩展它的行为。然而,与大多数功能强大的框架一样,其中有些设置参数并不能很好地工作,某些类型的任务需要特定的执行策略,而一些参数组合则可能产生奇怪的结果。