Executors 工具类提供了四种不同的线程池来帮助我们创建不同需求的线程池:
1.newCachedThreadPool():
这是一个可以缓存的线程池,当有新任务时,如果线程池内有空闲线程,则使用空闲线程,如果线程池内没有空闲线程,则新建一个线程执行任务。空闲线程超过60秒会被回收掉。
2.newFixedThreadPool(int nThreads):
这是一个定长的线程池,线程池内的线程个数是固定的。当任务超出固定个数会在阻塞队列中等待。
3.newSingleThreadExecutor():
这是一个单线程的线程池,只有唯一的一个工作线程,会按照顺序来执行任务。
4.newScheduledThreadPool(int corePoolSize):
这是一个定长线程池,但他支持定时执行任务,或者周期性执行任务。
通过查看Executors的源码,会发现前三个线程池是调用了ThreadPoolExecutor的构造函数,只有最后一个线程池是调用了ScheduledThreadPoolExecutor的构造函数,不过该类是继承了ThreadPoolExecutor,只是在此基础上提供了一些延迟执行和周期性执行的方法。为了更了解线程池,就要去看ThreadPoolExecutor的构造函数。
ThreadPoolExecutor
ThreadPoolExecutor提供了四个构造函数,但最后都会调用参数最全的构造函数进行初始化。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 代码省略......
}
构造函数中的参数的含义:
corePoolSize:核心线程数,即在该线程池中运行的线程池个数。
maximumPoolSize:线程池最大线程数,即线程池最多可以创建的线程个数。
keepAliveTime:非核心线程的存活时间。
unit:keepAliveTime的单位,有7种取值。TimeUnit.DAYS、TimeUnit.HOURS、TimeUnit.MINUTES、TimeUnit.SECONDS、TimeUnit.MILLISECONDS、TimeUnit.MICROSECONDS、TimeUnit.NANOSECONDS。
workQueue:任务超过核心线程数后,被放置的阻塞队列。例如LinkedBlockingQueue。
threadFactory:线程工厂,用来创建线程。
handler:饱和策略,当阻塞队列已满,并且线程数已达到最大线程数时,会对新任务采取的策略。
线程池处理任务的流程
线程池被创建好以后,如果有任务被提交到线程池,线程池的处理逻辑如下:
1.判断是否所有的核心线程都在执行任务,如果有核心线程处于空闲状态或者现有的核心线程没有达到最大值,那么就会复用该空闲线程或者创建一个新的核心线程来执行该任务。否则进入2
2.判断阻塞队列是否已满,如果没有满就会将任务放至该阻塞队列中等待。否则进入3
3.判断当前线程数是否超过线程池最大线程数,如果没有超过,那么创建一个新的线程来执行该任务。否则执行饱和策略来处理该任务。