Executor框架中有一部分是任务执行部分,任务执行部分包括任务执行的核心接口Executor以及继承Executor接口的ExecutorService接口,ExecutorService接口有两个重要的实现类,ThreadPoolExecutor和ScheduledPoolExecutor两个实现类
ThreadPoolExecutor是线程池的核心类,通过Executors工具类可以实现三种类型的ThreadPoolExecutor:
FixedThreadPool:可重用的固定线程数的线程池,可重用的固定线程数,核心线程池和线程池的数目是一致的都与设置的线程数目相同,FixedThreadPool一般为了要满足资源的管理而限制当前线程数量的场景,一般用于负载较重的服务器
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads ,nThreads,0l,TimeUnit.millisecondes,new LinkedBlockingQueue())
}
FixedThreadPool创建的线程池,当线程的数目大于corePoolSizede的时候,keepAliveTime为空闲线程等待新任务的最长时间(最长的存活时间),超过这个时间之后将会被终止,0L表示线程池中只要有空余的线程,就会立即终止
FixedThreadPool执行execute()方法,1.如果当前线程的数目数目小于corePoolSize核心线程池数,同样小于最大线程池数目maximum,这个时候将会创建新线程来执行任务2.在线程池预热之后,当前线程池中运行的线程数目等于核心线程池数目,则提交的任务将被加入到LinkedBlockingQueue中,3.当线程池执行完任务之后,会在循环中反复从LinkedBlockingQueue中取出任务进行执行。
需要注意的是FixedThreadPool使用的LinkedBlockingQueue作为阻塞队列,这种情况下,当线程池中的线程的数目达到了corePoolSize,submit()execute()提交的所有的任务都会保存在LinkedBlockingQueue中,线程池的数目用于也不会超过corePoolSize,因此,maximum是一个无效值,在fixedThreadPool中等于corePoolSize,keepAliveTime是固定值为0,同时以为使用无界队列,运行中的FixedThreadPool不会拒绝任务不会调用,RejectExeccutionHandler中的rejectExecution方法
singleThreadExecutor是使用单个工作者线程的Executor,就是说创建线程池的时候,核心线程池大小和最大线程池的大小值为1,单个工作者线程的线程池除了线程池的大小不同之外,其他内容都是相同的,SingleThreadExecutor使用于需要保证顺序的执行工作任务,在各个时间点不会有多个线程的场景
CachedThreadPool是一个会根据需要创建新线程的线程池,核心线程池的数目为0,工作线程池的数目为无穷大即maximum为无界的,空闲线程等待新任务的最长时间为60,时间单位是seconds,使用的阻塞队列是不存储元素的阻塞队列,每个插入操作必须要等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常大于LinkekdBlockingQueue,不同于FixedThreadPool和SingleThreadExecutor,它采用的是没有容量的synchronousQueue作为阻塞队列,当任务过多的时候,需要不断的创建工作线程从阻塞队列中获取任务,极端情况下,CachedThreadPool会因为创建过多的线程而耗尽CPU和内存的资源,使用于执行很多短期异步的任务的小程序或者负载比较轻的服务器
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.seconds,new synchronousQueue())
}
ScheduledThreadPoolExecutor继承了TreadPoolExecutor主要是用来延迟执行任务,或者是 定期执行任务,为了实现周期性执行任务,对TreadPoolExecutor做了三方面的修改,使用DelayQueue作为任务队列,获取任务的方式不同,在执行周期性任务后 增加了额外的修改。DelayQueue是一个无界队列所以ThreadPoolExecutor中的maximum在ScheduledThreadPoolExecutor中没有什么意义。
scheduleThreadPoolExecutor的执行首先调用**ScheduleAtFixedRate()方法或者scheduleWithFixedDelay()**方法的时候,向DelayQueue队列中添加一个实现了RunnableScheduledFuture接口的ScheduledFutureTask。之后,线程池中的线程从DelayQueue中获取ScheduledFutureTask,然后执行任务 。具体来说,ScheduledThreadPoolExecutor会把待调度的任务ScheduledFutrueTask添加到DelayQueue队列中,