线程池:ThreadPoolExecutor类
最重要构造方法:
public ThreadPoolExecutor(int corePoolSize,int maxPoolSize,long keepAliveTime,
TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
新来一个任务时候:
如果当前运行线程数量小于corePoolSize,则线程池会直接创建线程来执行任务,即使此时线程池中存在空闲线程;
如果当前运行线程数量>=corePoolSize,
a.如果任务队列有空余位置,则将任务加入队列
b.如果任务队列没有空余位置,
1)如果当前运行线程数量<maxPoolSize,则直接创建一个线程运行该任务
2) 根据拒绝策略处理该任务
corePoolSize 指核心线程数大小,一般情况下,线程池中的线程数不会超过此值
maxPoolSize 指线程池能允许的最大线程数大小。当任务提交过快,需要提高处理速率的时候,
线程池会生成更多的线程,此时线程数可能会超过corePoolSize,但不会超过maxPoolSize
keepAliveTime 如果当前线程数超过了corePoolSize,但是存在一些空闲的线程的话,这些空闲线程存活时间不会超过这个值
unit 配合keepAliveTime使用
workQueue 任务缓存队列
threadFactory 线程工程,用来创建线程
handler 任务拒绝提交策略
线程池状态
ThreadPoolExecutor有以下两种关闭方法:
void shutdown()
void shutdownNow()
配合这两种关闭方法,有4中线程池状态:RUNNING,SHUTDOWN,STOP,TERMINATED
当创建一个线程池的时候,线程池处于RUNNING状态;
当调用shutdown()方法时,线程池处于SHUTDOWN状态,此时线程池不接受新的任务,但会等待所有任务执行完毕;
当调用shutdownNow()方法时,线程池处于STOP状态,此时线程池不接受新的任务,并且会尝试终止正在执行的任务;
当线程池处于SHUTDOWN或者STOP状态,且所有的工作线程都已经被销毁,任务缓存队列清空之后,线程池处于TERMINATED状态。
任务提交和执行的过程
当线程池状态处于RUNNING时,提交一个任务:
有界的任务提交:使用ArrayBlockingQueue实现(指定其大小)
1.如果当前线程池中线程数量 <corePoolSize 的话,则直接创建一个线程去执行这个任务
2.如果当前线程数 >=corePoolSize 的话,
a. 如果任务缓存队列有空位,则将该任务放入队列,等待线程执行
b. 如果任务缓存队列已经满了:
a) 如果当前线程数 <maxPoolSize ,则直接创建一个新的线程去执行这个任务
b) 若果当前线程数 >=maxPoolSize, 则采取拒绝策略,不允许加入任务
无界的任务提交:使用LinkedBlockingQueue实现
1.如果当前线程池中线程数量 <corePoolSize 的话,则直接创建一个线程去执行这个任务
2.如果当前线程数 >=corePoolSize 的话,将任务加入缓存队列
直接提交队列:使用SynchronousQueue实现
1.如果当前线程池中线程数量 <corePoolSize 的话,则直接创建一个线程去执行这个任务
2.如果当前线程数 >=corePoolSize 的话,
a. 如果当前线程数 <maxPoolSize ,则直接创建一个新的线程去执行这个任务
b. 若果当前线程数 >=maxPoolSize, 则采取拒绝策略,不允许加入任务
优先级任务队列:使用PriorityBlockingQueue实现
是一个特殊的无界任务队列,在无界任务队列的基础上考虑了任务的优先级。(前三队列是先进先出,而该队列根据优先级来调度任务)
在线程数 >corePoolSize,且 <=maxPoolSize的时候,选定一个空闲线程,如果该空闲线程的空闲时间超过keepAliveTime(配合TimeUnit)的话,该线程会被终止。知道线程数量不超过corePoolSize
利用工程方法创建线程池
Executors中有静态方法:
public static ExecutorService newFixedThreadPool(int nThreads)
此时,corePoolSize=maxPoolSize=nThreads,使用LinkedBlockigQueue。
当提交任务很频繁,而任务又比较耗时的话,队列会快速膨胀,容易耗尽系统资源
public static ExecutorService newSingleThreadExecutor()
此时,corePoolSize=maxPoolSize=1,使用LinkedBlockigQueue。
是newFixedThreadPool(1)的简写
public static ExecutorService newCachedThreadPool()
此时,corePoolSize=0,maxPoolSize=无穷大,使用SynchronousQueue。
提交任务时,有空闲线程的话就使用空闲线程,没有就创建新线程。
当提交任务很频繁,而任务又比较耗时的话,会创建大量的线程,容易耗尽系统资源
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
注:ThreadPoolExecutor类和ScheduledExecutorService都继承了ExecutorService
拒绝策略
向线程池添加任务,如果该任务不能向线程池中添加的话,会执行拒绝策略。
四种拒绝策略如下:
AbortPolicy:直接抛出异常
CallerRunsPolicy:如果线程池没有被关闭,则在调用线程中,执行该被丢弃的任务。注意,这会影响调用线程的性能
DiscardOledestPolicy:丢弃最老的一个任务(即将被执行的那个任务),然后尝试再次提交
DiscardPolicy:不做任何处理。