首先,从ThreadPoolExecutor类图中,Executors其实是个工具类,里面提供了好多静态方法,这些方法根据用户选择返回不同的线程池实例。ThreadPoolExecutor继承了AbstractExecutorService,成员变量ctl是一个Integer的原子变量,用来记录线程池状态和线程池中线程个数,类似于ReentrantReadWriteLock使用一个变量来保存两种信息。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));((高3位)用来表示线程池状态,(低29位)用来表示线程个数;默认是RUNNING状态,线程个数为0)
private static final int COUNT_BITS = Integer.SIZE - 3;(线程个数掩码位数,因为不是所有平台的int类型都是32位,所以是具体平台下Integer的二级制位数-3后的剩余位数所表示的数才是线程个数)
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;(线程最大个数(低29位)00001111...1111)
private static final int RUNNING = -1 << COUNT_BITS;((高3位)1110...0000)
private static final int SHUTDOWN = 0 << COUNT_BITS;((高3位)0000...0000)
private static final int STOP = 1 << COUNT_BITS;((高3位)0010...0000)
private static final int TIDYING = 2 << COUNT_BITS;((高3位)0100...0000)
private static final int TERMINATED = 3 << COUNT_BITS;((高3位)0110...0000)
private static int runStateOf(int c) { return c & ~COUNT_MASK; }(获取高3位(运行状态))
private static int workerCountOf(int c) { return c & COUNT_MASK; }(获取低29位(线程个数))
private static int ctlOf(int rs, int wc) { return rs | wc; }(计算ctl新值(线程状态与线程个数))
线程池状态
首先,在ThreadPoolExecutor类中有一个Integer类型的原子变量ctl,用来记录线程池状态和线程池中线程个数。其中高3位用来表示线程池状态,低29位用来记录线程池线程个数。
RUNNING:接收新任务并且处理阻塞队列里的任务。
SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务。
STOP:拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务。
TIDYING:所有任务都执行完(包含阻塞队列里的任务)后当前线程池活动线程数为0,将要调用terminated()方法。
TERMINATED:终止状态,terminated()方法调用完成以后的状态。
线程池状态转换
RUNNING->SHUTDOWN:显式调用了shutdown()方法,或者隐式调用了finalize()方法里面的shutdown()方法。
RUNNING/SHUTDOWN->STOP:显式调用了shutdownNow()方法。
SHUTDOWN->TIDYING:当线程池和任务队列都为空时。
STOP->TIDYING:当线程池为空时。
TIDYING->TERMINATED:当terminated()方法执行完成时。
线程池参数
corePoolSize:线程池核心线程个数
maximumPoolSize:线程池最大线程数量
keepAliveTime:存活时间。如果当前线程池中的线程数量比核心线程数量多,并且是闲置状态,则这些闲置的线程能存活的最大时间。
TimeUnit:存活时间的时间单位。
workQueue:用于保存等待执行的任务的阻塞队列。比如基于数组的有界ArrayBlockingQueue,基于链表的无界LinkedBlockingQueue,最多只有一个元素的同步队列SynchronousQueue,优先级队列PriorityBlockingQueue等。
ThreadFactory:创建线程的工厂。可以自定义线程的一些属性,比如名称或者守护线程等
RejectedExecutionHandler:饱和策略。当队列满并且线程个数达到maxmumPoolSize后采取的策略。ThreadPoolExecutor中提供了四个公开的内部静态类:AbortPolicy(默认)(丢弃任务并抛出RejectedExecutionException异常)、DiscardPolicy(不推荐)(丢弃任务,但是不抛出异常)、DiscardOldestPolicy(调用poll()丢弃一个任务,执行当前任务)、CallerRunsPolicy(使用调用者所在线程来运行任务)
阻塞队列的有界和无界
阻塞队列的有界和无界是指队列的容量大小是否有限制。
有界队列是指队列的容量是固定的,即在创建队列时就指定了队列的容量大小,一旦队列达到了容量上限,再往队列中添加元素就会被阻塞,直到有其他线程从队列中取出元素为止。
无界队列则是指队列的容量大小没有限制,即队列可以无限制地增长,当队列中没有元素时,从队列中获取元素的操作将会被阻塞,直到有元素可用。
在实际应用中,选择有界队列还是无界队列取决于具体的业务需求和使用场景。
如果在队列容量有限的情况下需要保证高效的资源利用和线程安全,可以选择有界队列。
如果希望队列能够无限制地增长,可以选择无界队列,但需要注意可能会导致内存溢出等问题。