ThreadPoolExecutor 线程池

本文详细介绍了Java中的ThreadPoolExecutor线程池,包括构造参数解析、执行流程、内部结构、线程池状态转换及终止策略。讨论了核心线程数、最大线程数、线程存活时间等概念,并解释了工作队列、线程工厂、拒绝策略等关键机制。还深入探讨了线程池在不同状态下如何处理任务,如shutdown、shutdownNow的区别以及线程池的生命周期管理。
摘要由CSDN通过智能技术生成

ThreadPoolExecutor

基础描述

ThreadPoolExecutor作为JUC对外提供基础实现,以线程池的形式对外提供管理任务执行,线程调度。

ThreadPoolExecutor构造函数

//ThreadPoolExecutor线程池的构造函数,

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue<Runnable> workQueue,

                          ThreadFactory threadFactory,

                          RejectedExecutionHandler handler) {

    ......

}

参数说明

1. corePoolSize:表示该线程池最小的工作线程数(常驻线程数/并行度)。

==>默认情况下,当需要使用时创建线程,也可以调用 prestartAllCoreThreads() 方法进行预创建所有的核心线程。

2. maximumPoolSize:表示该线程池最大的线程数量,线程池中最大运行的线程数(添加阻塞队列失败会直接运行).

==>理论上可将其设置为Integer.MAX_VALUE,

==>这个值必须大于等于corePoolSize,如果等于corePoolSize那么keepAliveTime在默认情况下就失去了意义。

3. keepAliveTime:表示空闲线程的超时时间,(单位为纳秒)。

4. unit:表示空闲线程超时的时间单位,与keepAliveTime配合使用

==>TimeUnit中的值,SECONDS(秒),MINUTES(分),HOURS(小时),DAYS(天) 。

5. workQueue :表示工作队列(其实是一个runnable队列,在线程池中定义为Worker),

==>需要是BlockingQueue(阻塞队列)的实现类。

6. threadFactory:线程工厂,用于给线程池生成新的线程。

==>需要实现ThreadFactory接口,默认为: Executors.DefaultThreadFactory

7. handler:当workQueue队列线程数达到maximumPoolSize时,创建新线程错误时的处理策略。

==>其基类为RejectedExecutionHandler。默认为:AbortPolicy,

==>可选(AbortPolicy,DiscardPolicy,DiscardOldestPolicy)。

====>AbortPolicy=>抛出RejectedExecutionException异常

====>DiscardPolicy=>抛弃当前的任务

====>DiscardOldestPolicy=>抛弃旧的任务

====>CallerRunsPolicy=>重试添加当前的任务(自动重复调用execute函数)

在ThreadPoolExecutor预留了两个空函数体,用于Worker对线程执行前后进行拦截处理的函数。

//可以由ThreadPoolExecutor的继承类实现空函数体

//此函数用于在每个Worker(线程池中的线程)执行前进行调用处理.

protected void beforeExecute(Thread t, Runnable r) { }

//此函数用于在每个Worker执行后处理某些场景,如果线程执行完成后获取结果

protected void afterExecute(Runnable r, Throwable t) { }

//此函数用于线程池在终止前调用的处理场景,即state由TIDYING转换到TERMINATED前.

protected void terminated() { }

内部结构定义

用于维护线程池的运行状态与线程池中运行的线程数量的几个关键变量与常量

//ctl用于记录线程池运行状态(高3位)与线程池中线程的运行数量(低29位),

//==>即默认为运行状态,线程池线程数据为0

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

private static final int COUNT_BITS = Integer.SIZE - 3;

//低29位设置为0001 1111 1111 1111 1111 1111 1111 1111,代表线程池中运行的线程数量.

private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits

//高三位为111,1110 0000 0000 0000 0000 0000 0000 0000

//=>在该状态下,线程池接受新任务并会处理阻塞队列中的任务

private static final int RUNNING    = -1 << COUNT_BITS;

//高三位为000,0000 0000 0000 0000 0000 0000 0000 0000

//=>在该状态下,线程池不接受新任务,但会处理阻塞队列中的任务

private static final int SHUTDOWN   =  0 << COUNT_BITS;

//高三位为001,0010 0000 0000 0000 0000 0000 0000 0000

//=>在该状态下,线程池不接受新的任务且不会处理阻塞队列中的任务,并且会中断正在执行的任务

private static final int STOP       =  1 << COUNT_BITS;

//高三位为010,0100 0000 0000 0000 0000 0000 0000 0000

//=>所有任务都执行完成,且工作线程数为0,将要调用terminated方法

private static final int TIDYING    =  2 << COUNT_BITS;

//高三位为011,0110 0000 0000 0000 0000 0000 0000 0000

//=>最终状态,为执行terminated()方法后的状态

private static final int TERMINATED =  3 << COUNT_BITS;

// Packing and unpacking ctl

//取出ctl中的state部分(高三位的值),指定位取反并按位于,即把低29位全部设置为0

//====>因为CAPACITY是29位1.取反就全是0.

private static int runStateOf(int c)     { return c & ~CAPACITY; }

//取出ctl中的线程池中线程数量值,取低29位的值

private static int workerCountOf(int c)  { return c & CAPACITY; }

//这个函数作用于把state(高三位)与count(低29位)两个值合并到一个int(ctl)中

private static int ctlOf(int rs, int wc) { return rs | wc; }

shutdown时的状态转换

1,1,当调用:shutdown时,其状态由RUNNING状态转换为SHUTDOWN (状态)。

1,2,当调用:shutdownNow时,其状态(RUNNING or SHUTDOWN)转换为STOP。

2,1,当阻塞队列与线程池两者均为空时,状态由SHUTDOWN转换为TIDYING。

2,2,当线程池任务为空时,状态由STOP转换为TIDYING 。

3,当 terminated执行完成后,状态由 TIDYING 转换为 TERMINATED。

execute(执行线程)

通过线程池执行一个线程时通过调用execute或者submit(此函数返回一个Future)函数。

执行线程主要有几种情况:

1,如果线程池中正在运行的worker数量小于corePoolSize,直接添加worker到workers容器中并运行线程对应的worker.

2,如果线程数量超过corePoolSize时,会尝试添加worker到workQueue阻塞队列中,如果添加成功,等待coreWorkers线程通过getTask来获取worker并运行。

3,如果阻塞队列offer失败,此时线程数量小于maximumPoolSize时,会尝试启动一个新的worker到workers容器中,并运行。

4,其它情况,直接拒绝服务。

//mainLock锁:控制workers与largestPoolSize的线程安全

private final ReentrantLock mainLock = new ReentrantLock();

//当线程池中worker(运行线程)数量小于corePoolSize时,存储core线程的容器.

//==>此容器的线程安全由mainLock控制.

private final HashSet<Worker> workers = new HashSet<Worker>();

//BlockingQueue实例的阻塞队列,

private final BlockingQueue<Runnable> workQueue;

//ThreadPoolExecutor执行一个线程Runnable

public void execute(Runnable command) {

    //step0,要执行的线程不能为null,

    if (command == null)

        throw new NullPointerException();

    //得到当前ctl的值,包含有state与线程运行数量workerCount

    int c = ctl.get();

      //step1,判断ctl的低29位正在运行的线程数是否小于corePoolSize,

      //==>小于corePoolSize时,通过addWorker执行原子操作对workerCount加1,

     //==>利用mainLock锁添加worker到workers容器中并启动线程

//====>(启动失败会回滚wrokerCount与workers容器).

    if (workerCountOf(c) < corePoolSize) {

        if (addWorker(command, true))

            return;

        //添加失败,其它线程抢到资源,重新获取ctl的值

        c = ctl.get();

    }

    //step2,判断ctl的高三位是否是RUNNING状态,如果线程池状态正常添加线程到workQueue阻塞队列.

    //==>注意:添加到workQueue中的线程是等待运行的线程,此时workerCount不会变更.

    if (isRunning(c) && workQueue.offer(command)) {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值