ThreadPoolExecutor类的讲解


ThreadPoolExecutor类的讲解

参考文档地址1: 全网最详细的线程池 ThreadPoolExecutor 解读

1 线程池状态

五种状态:

线程池的状态说明
running 允许提交并处理任务
shutdown 不允许提交新的任务,但是会处理已提交的任务
stop 不允许提交任务,也不会处理阻塞队列中的未执行任务,并设置正在执行的线程的中断标志位
tidying 所有任务执行完毕,池中工作的线程数为0,等待执行terminated()勾子方法
terminated terminated()勾子方法执行完毕
  • 线程池的shutdown()方法,将线程池有running(运行状态)变为shutdown状态

  • 线程池的shutdownNow()方法,将线程池由running或shutdown状态转化为stop状态

注: shutdown状态和stop状态 先回转变为tidying状态,最终都会变为terminated

2 ThreadPoolExecutor构造函数:

ThreadPoolExecutor继承自AbstractExecutorService,而AbstractExecutorService实现了ExecutorService接口

3 线程池的核心参数

  1. corePoolSize 核心线程池的大小

  2. maximumPoolSize 线程池最多能创建的线程数

  3. workQueue 阻塞队列,用于保存任务的阻塞队列

  4. keepAliveTime 空闲线程存活时间

  5. unit 时间单位

  6. threadFactory: 创建线程工的工程类

  7. handler 饱和策略(拒绝策略)

 

keepAliveTime当一个线程无事可做,超过一定的时间keepAliveTime时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉;所以线程吃的所有任务完成后,他最终会收缩到corePoolSize的大小

注:如果线程池设置了allowCoreThreadTimeout参数为true(默认false),那么当空闲线程超过keepaliveTime后直接停掉。(不会判断线程数是否大于corePoolSize)即:最终线程数会变为0

workQueue:它决定了缓存任务的排队策略

ThreadPoolExecutor线程池推荐了三种等待队列,它们是:SynchronousQueue,LinkedBlockingQueue和ArrayBlockingQueue

有界队列

  • SynchronousQueue:一个不存储元素的阻塞队列

  • ArrayBlockingQueue:一个由数组支持的有界阻塞队列

无界队列

实际上任何无限容量的队列/栈都是有容量的,这个容量就是Integer.MAX_VALUE

  • LinkedBlockQueue:基于链表结构的无界队列;

  • PriorityBlockingQueue:是一个按照优先级进行内部元素排序的无界阻塞队列

如果BlockingQueue是无界的,那么永远不会触发maximumPoolSize,自然keepAliveTime也就没有了意义。

4 线程池的工作原理

当调用线程池的executor()方法添加一个任务时,线程池会做如下判断:

  • 如果有空闲线程,则直接执行该任务;

  • 如果没有空闲线程,且当前运行的线程数少于corePoolSize,则创建新的线程执行该任务;

  • 如果没有空闲线程,且当前线程等于corePoolSize,同时阻塞队列未满,则将任务加入队列,而不添加新的线程;

  • 如果没有空闲线程,且阻塞队列已满,同时池中的线程数少于maximumPoolSize,则创建新的线程执行该任务;

  • 如果没有空闲线程,且阻塞队列已满,同时池中的线程数等于maximumPoolSize,则根据构造函数中的handler指定的策略来拒绝新的任务

 

 

5 handler拒绝策略

策略描述
AbortPolicy() 抛出异常,由开发人员进行处理,默认策略
CallerRunsPolicy() 由向线程池提交任务的线程来执行该任务
DiscardPolicy 抛弃当前的任务
DiscardOldestPolicy() 抛弃最旧的任务

最科学的的还是 AbortPolicy 提供的处理方式

6 常用的方法

除了在创建线程池时指定上述参数的值外,还可在线程池创建以后通过如下方法进行设置。

图片

此外,还有一些方法:

  • getCorePoolSize():返回线程池的核心线程数,这个值是一直不变的,返回在构造函数中设置的coreSize大小;

  • getMaximumPoolSize():返回线程池的最大线程数,这个值是一直不变的,返回在构造函数中设置的coreSize大小;

  • getLargestPoolSize():记录了曾经出现的最大线程个数(水位线);

  • getPoolSize():线程池中当前线程的数量;

  • getActiveCount():Returns the approximate(近似) number of threads that are actively executing tasks;

  • prestartAllCoreThreads():会启动所有核心线程,无论是否有待执行的任务,线程池都会创建新的线程,直到池中线程数量达到 corePoolSize;

  • prestartCoreThread():会启动一个核心线程(同上);

  • allowCoreThreadTimeOut(true):允许核心线程在KeepAliveTime时间后,退出;

7 Executors类:

Executors类的底层实现便是ThreadPoolExecutor!Executors 工厂方法有:

  • Executors.newCachedThreadPool():无界线程池,可以进行自动线程回收

  • Executors.newFixedThreadPool(int):固定大小线程池

  • Executors.newSingleThreadExecutor():单个后台线程

它们均为大多数使用场景预定义了设置。不过在阿里java文档中说明,尽量不要用该类创建线程池。

 

 

posted @ 2022-05-26 22:25  进击的小蔡鸟  阅读(38)  评论(0编辑  收藏  举报