Java源码分析之ThreadPoolExecutor(上)

创建线程池需要核心线程数,大于等于零即可,最大线程数,必须要大于零并且要大于等于核心线程数,线程存活时间以及时间单位,阻塞队列,线程工厂,拒绝策略。


public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

线程池的主要属性和部分主要方法如下,线程池状态和线程数量用一个int的32位表示,后29位表示线程数量,前三位表示线程池状态,通过位运算可以知道具体的状态和数量,cas操作可以增加减少线程数量。


private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

// 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; }
private static boolean runStateLessThan(int c, int s) {
    return c < s;
}
private static boolean runStateAtLeast(int c, int s) {
    return c >= s;
}
private static boolean isRunning(int c) {
    return c < SHUTDOWN;
}
private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);
}
private boolean compareAndDecrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect - 1);
}
private void decrementWorkerCount() {
    do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}

线程池执行任务的核心方法如下,从表面看,首先判断目前的线程数量是否小于核心数,小于的话就加线程,否则的话就是判断是运行状态往队列中加任务,成功的话再次判断运行状态,然后状态异常的话就移除该任务,执行拒绝策略,否则就判断当期那线程数,如果目前没有线程的话,就增加一个线程,如果刚开始就不是运行状态或者往队列中添加任务失败的话就直接添加新的线程,这里会判断最大线程数量,超过最大的话就执行拒绝策略。


public void execute(Runnable command) {
    if (command == null)
            throw new NullPointerException();
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    else if (!addWorker(command, false))
        reject(command);
}

小于核心数量直接增加线程,首先判断当前状态,决定是否可以添加新的线程,当状态值大于等于SHUTDOWN时,就说明线程池即将关闭,不创建新线程的情况:当状态不等于SHUTDOWN时说明线程池要马上退出,哪怕队列中还有任务,或者当状态为SHUTDOWN但是任务不为空,说明这个线程是直接通过执行任务创建的,并不是线程池后来补充的线程,补充的话有可能之前的线程出现异常,还有就是当状态为SHUTDOWN而且任务为空,但是这个时候队列也为空的话,就没有创建新线程的必要了。

计算当前线程数量并且与线程的最大容量比较,超过29位所能代表的最大值的话也不能创建新线程,然后根据是否核心标志来判断当前线程数量是否超过核心数或者最大数。校验完毕后增加线程数量,如果cas操作失败的话就重新获取标志位,判断状态是否被更改,重新执行一遍流程。


private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }
}

创建新线程,获取重入锁,保证线程安全,获取标志位判断当前状态小于SHUTDOWN代表正常运行状态,或者在SHUTDOWN状态下还有任务没有执行完需要创建新的线程执行队列中的任务,把线程工作者加入到HashSet中,计算当前的线程数量,记录历史上同时存在的线程最大数量,线程最后添加成功的话,启动线程

private final class Worker extends AbstractQueuedSynchronizer implements Runnable
Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    this.thread = getThreadFactory().newThread(this);
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
    w = new Worker(firstTask);
    final Thread t = w.thread;
    if (t != null) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Recheck while holding lock.
            // Back out on ThreadFactory failure or if
            // shut down before lock acquired.
            int rs = runStateOf(ctl.get());

            if (rs < SHUTDOWN ||
                (rs == SHUTDOWN && firstTask == null)) {
                if (t.isAlive()) // precheck that t is startable
                    throw new IllegalThreadStateException();
                workers.add(w);
                int s = workers.size();
                if (s > largestPoolSize)
                    largestPoolSize = s;
                workerAdded = true;
            }
        } finally {
            mainLock.unlock();
        }
        if (workerAdded) {
            t.start();
            workerStarted = true;
        }
    }
} finally {
    if (! workerStarted)
        addWorkerFailed(w);
}
return workerStarted;

线程工作者启动失败的话,也就是线程添加失败,可能是状态已经大于SHUTDOWN,需要执行失败处理,前面增加了线程数量,这里要减去对应的数量,并且移除集合中的工作者


private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            workers.remove(w);
        decrementWorkerCount();
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}

尝试执行线程池终止方法,如果当前状态是正常运行状态或者已经至少是TIDYING状态,因为有别的线程已经执行了终止方法,不需要重复执行,或者是SHUTDOWN状态但是队列中还有任务需要执行,这些情况的话就不能再执行下面的方法。判断当前线程数量是否不等于零,如果等于零的话,说明线程已经全部退出,可以执行终止操作,先把状态设置为TIDYING,执行终止方法,最后设置为TERMINATED状态,通知所有监听终止状态的等待者。

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                    terminated();
                } finally {
                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

遍历工作者集合,中断第一个线程,已经是中断状态或者没有获取到状态锁也算已经中断过,可以直接返回。

private void interruptIdleWorkers(boolean onlyOne) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        for (Worker w : workers) {
            Thread t = w.thread;
            if (!t.isInterrupted() && w.tryLock()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                } finally {
                    w.unlock();
                }
            }
            if (onlyOne)
                break;
        }
    } finally {
        mainLock.unlock();
    }
}

尝试获取状态锁,当线程在执行任务的时候这个锁是获取不到的。

public boolean tryLock()  { return tryAcquire(1); }
protected boolean tryAcquire(int unused) {
    if (compareAndSetState(0, 1)) {
        setExclusiveOwnerThread(Thread.currentThread());
        return true;
    }
    return false;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值