JUC ThreadPoolExecutor源码

107 阅读2分钟

1.简介

ThreadPoolExecutor是JUC包下的线程池类,同样Spring包下也有一个ThreadPoolTaskExecutor,主要是对ThreadPoolExecutor的包装,增加回调方法以及增加bean化管理等相关功能,其核心依旧是ThreadPoolExecutor,本文只讨论ThreadPoolExecutor.

2.类信息

2.1 继承关系

image.png

ThreadPoolExecutor继承自AbstractExecutorService,很熟悉的模板方法类,子类重写了很多模板方法,但 submit()方法是完全继承AbstractExecutorService的.

2.2 静态变量

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //原子操作,初始状态为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;  // 所有任务完成,即将调用ternaminated()
private static final int TERMINATED =  3 << COUNT_BITS;  // ternaminated()调用完成

//RUNNING:    11100000 00000000 00000000 00000000 
//SHUTDOWN:   00000000 00000000 00000000 00000000 
//STOP:       00100000 00000000 00000000 00000000 
//TIDYING:    01000000 00000000 00000000 00000000 
//TERMINATED: 01100000 00000000 00000000 00000000

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

ctl一个属性就代表了线程池状态+工作线程数, 用一个int字段表示两个字段,类似于ReentrantReadWriteLock中使用一个int表示读锁和写锁的个数.

为啥用一个属性来表示?? 直接两个变量不是更好更清楚?系统缺这么点内存空间?? 好处嘛当然有,当同时需要改变两个字段时,可以避免加锁(因为两个字段需要同步原子化修改),直接用一个运算就可以完成了

image.png

2.3 成员变量

private final BlockingQueueèRunnableé workQueue; //阻塞队列
private final ReentrantLock mainLock =new ReentrantLock();//锁
private final HashSetèWorkeré workers =new HashSet<Worker>(); //工作线程的封装
private final Condition termination =mainLock.newCondition(); //terminate同步状态
private int largestPoolSize; //最大线程数
private long completedTaskCount;  //完成任务数
private volatile ThreadFactory threadFactory;  //线程工程
private volatile RejectedExecutionHandler handler; //拒绝策略
private volatile long keepAliveTime;
private volatile boolean allowCoreThreadTimeOut; //是否保障核心线程始终存货
private volatile int corePoolSize; //核心线程数
private volatile int maximumPoolSize; //最大线程数

2.4 内部类

private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    /**
     * This class will never be serialized, but we provide a
     * serialVersionUID to suppress a javac warning.
     */
    private static final long serialVersionUID = 6138294804551838833L;

    /** Thread this worker is running in.  Null if factory fails. */
    final Thread thread;
    /** Initial task to run.  Possibly null. */
    Runnable firstTask;
    /** Per-thread task counter */
    volatile long completedTasks;

    /**
     * Creates with given first task and thread from ThreadFactory.
     * @param firstTask the first task (null if none)
     */
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

    /** Delegates main run loop to outer runWorker  */
    public void run() {
        runWorker(this);
    }

    // Lock methods
    //
    // The value 0 represents the unlocked state.
    // The value 1 represents the locked state.

    protected boolean isHeldExclusively() {
        return getState() != 0;
    }

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

    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }

    public void lock()        { acquire(1); }
    public boolean tryLock()  { return tryAcquire(1); }
    public void unlock()      { release(1); }
    public boolean isLocked() { return isHeldExclusively(); }

    void interruptIfStarted() {
        Thread t;
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}