首先,介绍线程池的概念。
简单讲,就是有一个“池”内放着一些已经启动的线程,这些线程一直启动,用来执行线程池接受的任务。这些线程我们称为核心线程。
当接收任务过多时,会进入阻塞队列进行存储。
而如果阻塞队列也满,则会创建线程来执行任务,这些任务称为救急线程。救急线程任务结束后会根据存活时间来释放
ThreadPoolExecutor的创建参数就是基于上述的概念:
ThreadPoolExecutor(int corePoolSize,//核心线程数目
int maximumPoolSize,//最大线程数 = 核心线程数 + 救急线程数
long keepAliveTime,//救急线程的存活超时时间
TimeUnit unit,//超时时间的单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,主要用于给线程起名,
RejectedExecutionHandler handler)//拒绝策略,即队列满了后再接受任务怎么处理
会有多种构造方法,常用的是前5个参数的构造。本质上都是调用了这个构造方法
ThreadPoolExecutor类继承自AbstractExecutorService类,而AbstractExecutorService类实现了ExecutorService接口。(因为后面工具类的返回值是ExecutorService接口对象,而不是ThreadPoolExecutor对象)。线程池操作都定义在ExecutorService接口中。
根据不同的需求,会产生不同的线程池。为了方便,有了Executors类来创建一些常用的线程池,注意的是返回值是ExecutorService对象
需求一:固定大小的线程池,即Executors.newFixedThreadPool(corePoolSize)。是只有一定数量的核心数量(参数),即核心数目等于总数目。阻塞队列使用的是LinkedBlockingQueue<Runnable>。适应于任务数量已知,且相对耗时
本质是调用了
ThreadPoolExecutor(corePoolSize,coreSize,0,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>() )
需求二、带缓冲区的线程队列,即Executors.newCachedThreadPool()。没有核心线程,全都是救急线程。超时时间设为60秒。阻塞队列使用的是SynchronousQueue<Runnable>。 该队列没有容量,没有线程取任务是不能够放任务的。
本质调用:
ThreadPoolExecutor(0,Integer.MAx_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>() )
需求三:单线程线程池:即Executors.newSingleThreadPool() , 即需求一的特殊情况,只有一个核心线程。即:
ThreadPoolExecutor(1,1,0,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>() )