Executor框架的线程池

Executor框架的线程池有:FixedThreadPool、SingleThreadExecutor、CachedThreadPool、ScheduledThreadPoolExecutor。本文介绍每个线程池的实现原理。

1.FixedThreadPool

是固定线程数的线程池。

原理:
1)如果当前运行的线程数少于corePoolSize,则创建新线程来执行任务。
2)在线程池完成预热后(当前运行的线程数目等于corePoolSize),将任务加入到LinkedBlockingQueue(无界队列)。
3)线程执行完1)中的任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行。

2.SingleThreadExecutor

是使用单个worker线程的Executor。

原理:

1)如果当前运行的线程数少于corePoolSize(即线程池中无运行的线程),则新创建一个线程来执行任务。

2)在线程池完成预热后(即当前线程池里有一个运行的线程),将任务加到LinkedBlockingQueue(无界队列)。

3)线程执行完1)中的任务后,会在一个无限循环中反复从LinkedBlockingQueue获取任务来执行。

3.CachedThreadPool

CachedThreadPool使用了没有容量的堵塞队列SynchronousQueue,该队列的特点是每个插入操作必须等待另一个线程的对应移除操作。这里插入的操作由主线程来做,移除的操作由线程池里空闲的线程来做。

CachedThreadPool的corePoolSize被设置为0,maximumPoolSize被设置为Integer.MAX_VALUE,即maximumPool是无界的。会为空闲线程设定一个超时时间,如果空闲线程空闲时间超过了这个超时时间,该线程就会终止。

执行步骤:

1)主线程首先执行SynchronousQueue.offer(Runnable task),如果当前线程池中有空闲线程正在执行Synchronous.poll(),那么主线程的offer操作和空闲线程的poll操作配对成功,主线程会把任务交给空闲线程执行;

2)如果线程池中没有空闲线程,或者线程池中没有线程,此时CachedThreadPool会创建一个新线程执行任务;

3)步骤2)中创建的线程执行完任务后,会执行poll操作,如果空闲线程在超时时间内没有通过poll操作找到匹配的offer操作,那么就会终止;

4.ScheduledThreadPoolExecutor

ScheduleThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。

其原理可以分为如下几个步骤:

1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()或者scheduleWithFixedDelay()方法时,会向DelayQueue中添加一个ScheduledFutureTask。(注:DelayQueue是一个无界队列,所以设置maximumPoolSize的大小无意义)

2)DelayQueue封装了一个PriorityQueue,这个PriorityQueue会对队列中的ScheduledFutureTask进行排序。排序的规则和ScheduledFutureTask包含的属性有关,主要包含3个属性:time,表示这个任务将要被执行的具体时间;sequenceNumber表示这个任务被添加到ScheduledThreadPoolExecutor中的序号;period,表示任务执行的间隔周期。排序的规则就是time小的排在前面(时间早的任务将被先执行),如果两个ScheduledFutureTask的time相同,就比较sequenceNumber,sequenceNumber小的排在前面(如果两个任务的执行时间相同,那么先提交的任务将被先执行);

3)线程池中的线程从DelayQueue中获取已到期的ScheduledFutureTask(DelayQueue.take()),到期任务指的是ScheduledFutureTask的time大于等于当前时间;

4)线程执行获取到的ScheduledFutureTask;

5)线程修改ScheduledFutureTask的time变量为下次将要被执行的时间;

6)线程把这个修改time之后的ScheduledFutureTask放回DelayQueue(DelayQueue.add())。

你可能感兴趣的:(Executor框架的线程池)