概述
ThreadPoolExecutor
,它是Executors.newXxxxx()
的返回结果,像Executors.newCachedThreadPool();
,它实际上是这个:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
这是FixedThreadPool
的:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
所以ThreadPoolExecutor
是最为重要的,先了解下它的构造器参数:
public ThreadPoolExecutor(int corePoolSize,//线程池的核心线程数量
int maximumPoolSize,//线程池的最大线程数
long keepAliveTime,//当线程数大于核心线程数时,多余的空闲线程存活的最长时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列,用来储存等待执行任务的队列
ThreadFactory threadFactory,//线程工厂,用来创建线程,一般默认即可
RejectedExecutionHandler handler//拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务
) {
corePoolSize说明有多少个核心线程,核心线程的策略是添加任务时,目前的核心线程数量小于corePoolSize,就生成一个核心线程放进去核心线程池,并放入Runnable执行。并且,核心线程在任务执行完成后不会销毁,他会一直空转直至再次分配任务。
maximumPoolSize就是最大线程数,注意这个多的线程并不是一有任务来就会创建的,只有当任务队列满了,且已创建的线程数小于maximumPoolSize,线程池才会创建新的线程来执行任务。这也表明了核心线程的地位,只要不是紧急(队列满),核心线程会一直自个去处理。
- maxPoolSize > 当线程数 >= corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务
- 当线程数 = maxPoolSize,且任务队列已满时,线程池会根据拒绝策略进行处理
keepAliveTime、unit就是如果多余线程空闲了,在这个时间后,就销毁,免得占用资源。
最关键的还是这个workQueue,任务队列。一般而言它有三种选择:SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue。
SynchronousQueue看着像队列,但它不会存任何一个东西,当向队列插入任务时,它会一直阻塞直到有一个空闲线程取走它。如果使用SynchronousQueue,那maximumPoolSize就是表明线程池的线程最大允许数量,可以一直插入新任务直到满了。
LinkedBlockingQueue就是一个真的队列了,可以缓存需要等待的任务。使用LinkedBlockingQueue,如果不输入参数固定长度,队列理论可以无限长,所以不会创建除核心线程以外的线程,所以maximumPoolSize如同虚设(一般设为核心线程数),所以任务可以无限提交,永远不会满除非内存放不下,线程池会按顺序一一执行:此时就是一个生产者消费者模式;如果输入参数固定长度,就和ArrayBlockingQueue类似了。
ArrayBlockingQueue与LinkedBlockingQueue类似,但它是数组实现,所以是有界的。另外,为了同步,它的生产与消费使用的同一把锁;而LinkedBlockingQueue只在确定队列大小时,当队列满了才会加锁:这与数据结构有关。
关于BlockingQueue的研究
拒绝策略有4种,一是丢弃报错,二是丢弃不报错,三是丢弃最老的任务(顺序排第一位的)并提交该任务,四是调用线程(提交任务的线程)直接执行被丢弃的任务。默认是丢弃报错,业务中看业务需求选择。
线程池的五个状态
1、RUNNING
(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(02) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
2、 SHUTDOWN
(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
3、STOP
(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4、TIDYING
(1) 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5、 TERMINATED
(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
最后
以上就是迷你香氛为你收集整理的ThreadPoolExecutor的参数与线程池的五个状态线程池的五个状态的全部内容,希望文章能够帮你解决ThreadPoolExecutor的参数与线程池的五个状态线程池的五个状态所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复