(1)为何使用线程池
1.节约资源的开销
2.简化线程生命周期管理
(2)如何合理设计线程池大小
1.CPU密集型线:S=N+1;(CPU密集型指以计算为主)
2.IO密集型线:S=2*N+1;(IO密集型指IO操作为主,如读写操作)
3.混合型线程池最大为:S=N*U*(1+WT/ST)
注:S为线程池合理大小,N为CPU核心个数,U为CPU使用率,WT为任务线程等待时间,ST为任务线程执行时间
(3)线程饱和处理策略
1.ThreadPoolExecutor.AbortPolicy 直接抛异常
2.ThreadPoolExecutor.DiscardPolicy 丢弃任务不抛异常
3.ThreadPoolExecutor.DiscardOldestPolicy 丢弃等待最久的任务,尝试重新接纳被拒绝的任务
4.ThreadPoolExecutor.CallerRunsPolicy 在客户端线程中执行被拒绝的任务(线程不安全型)
(4)死锁(线程之间相互依赖)
1.线程与线程之间有依赖关系时,例如A任务依赖B任务,线程池都在执行行A任务而B任务一直处在队列等待状态,该状态会一致持续下去而造成死锁
2.解决方法:
解决方法一:
配置1:设置线程池的最大大小为一个有限值
配置2:使用SynchronousQueue作为工作队列(直接交接队列)
配置3:使用ThreadPoolExecutor.CallerRunsPolicy作为线程池饱和处理策略
采用上述配置能够避免死锁是因为前一个任务执行时调用后一个任务,后一个任务可以使用前一个任务的线程执行任务,相当于工作交接(我是这么理解的)
解决方法二:
可以采用多线程池,将A任务与B任务放在不同过的线程池去执行
3.用spring配置的的线程池,当注入queueCapacity属性的值为0时就会使用SynchronousQueue队列
(5)定时线程池ScheduledExecutorService可以对每个线程设定不同的频率。