Java线程池

从JDK1.5开始,Java API提供了Executor框架,创建不同的线程池。有单线程池、数目固定的线程池、缓存线程池
Executors线程池工厂提供了一些创建不同特性线程池ThreadPoolExecutor的方法,它们都返回ExecutorService对象:

  • Executors.newSingleThreadPool()
  • Executors.newFixedThreadPool(int size):定长线程池,可控制线程最大并发数,超出的线程在队列中等待。
  • Executors.newCachedTheadPool():适合很多生存期短的任务,空闲线程会在指定时间内被回收。
  • Executors.newScheduledThreadPool():定长线程池,支持定时及周期性任务执行

它们内部都是封装了ThreadPoolExecutor:

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 15, TimeUnit.SECONDS,new ArrayBlockingQueue(5), new ThreadPoolExecutor.CallerRunsPolicy());

线程池超载后的拒绝策略

池中的线程用光,等待队列也已排满。

扩展线程池

ThreadPoolExecutor提供了用于扩展的接口,比如要监控每个任务执行的开始和结束时间。

打印异常堆栈是排查问题的指南针,用线程池的execte()方法替换submit()方法,可以进而继承ThreadPoolExecutor来扩展出自己的TreaceThreadPoolExecutor。

Guava中扩展的线程池:

  • MoreExecutors.directExecutor() :将任务在调用线程中执行。
  • 将普通线程池转为Daemon线程池。
  • 对Future模式扩展。

估算线程池大小

threadsSize=cpu数量*cpu使用率*(1+等待时间/计算时间)

Fork/Join线程池

分而治之的思想,例如MapReduce,将大任务划分为小任务合成为最终结果。

ForkJoinPool线程池接受提交ForkJoinTask,ForkJoinTask对象可以调用fork()来分叉出小任务。