线程池之ThreadPoolExecutor(二)

属性

静态属性

COUNT_BITS=Integer.SIZE - 3=29;
CAPACITY  =00011111111111111111111111111111;
RUNNING   =11100000000000000000000000000000;
SHUTDOWN  =00000000000000000000000000000000;
STOP      =00100000000000000000000000000000;
TIDYING   =01000000000000000000000000000000;
TERMINATED=01100000000000000000000000000000;

// 控制符,初始值为RUNNING
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
ctl=RUNNING=11100000000000000000000000000000;
// 包装与解包控制符:Packing and unpacking ctl
private static int runStateOf(int c)     { return c & ~CAPACITY; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }

构造器参数,对应属性含义之前已经有介绍不再赘述:https://blog.csdn.net/u010597819/article/details/112758911

方法

ctlOf

根据线程池状态与线程数量生成ctl控制符,返回ctl值

应用
线程池进入下个运行状态

private void advanceRunState(int targetState) {
    for (;;) {
        int c = ctl.get();
        // 1. 如果目标状态小于当前状态直接返回,即不允许回滚状态
        if (runStateAtLeast(c, targetState) ||
            // 2. 复制当前线程数,并重新按照目标状态生成新的ctl控制符,cas执行变更
            ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
            break;
    }
}

workerCountOf

方法返回当前线程池线程数量

方法实现就是将ctl值与CAPACITY按位与运算,为什么这么计算也不多说,二者的二进制一看相信就没有疑问了,与运算可以理解为乘法运算,计算得出的正是当前任务数量。新增任务对ctl递增,完成任务则递减。

addWorker

添加任务并递增ctl

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        ...
        for (;;) {
            // 判断线程数超出最大限制直接返回添加任务失败
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // cas递增线程数
            if (compareAndIncrementWorkerCount(c))
                break retry;
            ...
}
private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);
}

runWorker

完成任务递减ctl

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            ...
            try {
                // 执行线程任务前置回调
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 执行线程任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    // 执行线程任务后置回调
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        // 任务等待队列已经没有值,正常完成作业的Worker
        // 如果执行任务抛出异常,跳出方法,不会执行到该行代码,即为默认值:completedAbruptly = true;
        completedAbruptly = false;
    } finally {
        // 完成作业的Worker执行退出逻辑
        processWorkerExit(w, completedAbruptly);
    }
}

processWorkerExit

退出Worker逻辑

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    // 1. 如果线程抛出异常,cas递减Worker
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
        // 1.1. 自旋方法,递减必须成功,否则自旋
        decrementWorkerCount();
    ...
    int c = ctl.get();
    if (runStateLessThan(c, STOP)) {
        // 2. 如果线程没有抛出异常则判断线程池水位
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            // 3. 如果线程数大于最小核心线程数,或者配置允许核心线程超时退出,
            //    则退出当前核心线程Worker
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        // 4. 否则(即不满足条件3),添加非核心Worker等待工作,直至超时或新任务进来
        addWorker(null, false);
    }
}

runStateOf

方法返回当前线程池工作状态

运算符优先级复习一波
1

CAPACITY取反后的值等于RUNNING,与ctl按位与运算,得到结果必然等于某个状态值,RUNNING除了高3位是1之外均为0,也就是除了高三位之外的位与0按位与运算结果均为0。

getTask

从等待队列获取任务执行

private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        // 如果当前线程池状态大于等于STOP,或者大于等于SHUTDOWN并且队列为空,
        // 则递减ctl并退出Worker
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }
        int wc = workerCountOf(c);
        // Are workers subject to culling?
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        // (线程数超出最大限制,或者(允许核心线程超时或者线程数超出了核心线程限制)并且已超时),
        // 并且,(线程数大于1,或者等待任务队列为空),则尝试递减ctl(非自旋)并退出当前Worker
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            // 尝试递减ctl(非自旋)并退出当前Worker
            if (compareAndDecrementWorkerCount(c))
                return null;
            // 尝试递减失败重新开始循环
            continue;
        }
        try {
            // 等待新任务,如果允许超时则设置等待超时时间等待新任务,否则永久阻塞等待新任务
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            // 已超时,标志为已超时状态
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

总结

  1. 使用位运算方式写代码可读性不高,好处是状态的判断以及数量的计算均通过位运算实现,性能高于常规算法写法
  2. ctl是32位Integer类型的控制符,首位是正负数标志位,高2-3位标志当前线程状态,低29位标志当前线程池线程数
  3. 2

退出Worker场景

  1. 用户线程正常完成,任务等待队列为空,并且允许核心线程超时并且已经超时,退出当前运行完成的Worker;任务等待队列不为空则保留一个Worker,如果线程池当前少于一个Worker则创建
  2. 用户线程抛出异常,并且允许核心线程超时并且已经超时,任务等待队列为空,退出当前运行完成的Worker;任务等待队列不为空则保留一个Worker,如果线程池当前少于一个Worker则创建
  3. 用户线程正常完成,任务等待队列为空,并且当前线程超出核心线程限制,退出当前运行完成的Worker
  4. 用户线程抛出异常,并且当前线程超出核心线程限制,退出当前运行完成的Worker
  5. 获取等待队列中的任务过程中判断当前线程池状态已经大于等于STOP状态,退出当前运行完成的Worker。注意此场景会忽略等待队列中的任务,即使有等待执行的任务也不会再启动线程作业。
  6. 获取等待队列中的任务过程中判断当前线程池状态已经等于SHUTDOWN状态,并且等待队列为空,执行步骤1,2,3,4的判断

退出Worker后立即生成新Worker场景

  1. 线程池状态小于STOP,用户线程抛出异常,创建新Worker
  2. 线程池状态小于STOP,用户线程正常完成,允许核心线程超时并且已经超时,如果任务等待队列不为空且线程池当前少于一个Worker则创建新Worker
  3. 线程池状态小于STOP,用户线程正常完成,不允许核心线程超时,如果当前线程池核心线程数小于配置的核心线程数则创建新Worker
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值