java8 ThreadPoolExecutor源码解析

线程池主要是为了减少任务执行的消耗(比如说创建线程的开销)和管理系统资源,今天我们来分析一下相关源码

继承关系如下:
ThreadPoolExecutor继承关系
我们自顶向下一个个进行分析

Executor

void execute(Runnable command);

这个接口只有一个方法,用于执行给定的任务command,很简单没啥好说的,这个类只要将任务的创建和调度分离开来,至于任务如何调度则需要看具体实现。

ExecutorService

在这里插入图片描述
可以看到ExecutorService继承自Executor,在原来的基础上提供了一些终止服务和提交任务(Runnable/Callable)的方法(这些方法返回的都是Future)。

方法说明
submit提交任务,不等待任务完成就立即返回Future
invokeAll批量提交任务,任务完成后返回Future列表
invokeAny批量提交任务,有一个任务完成就返回Future
shutDown调度器不会再接收新的任务,关闭调度器,但是不等待正在运行的任务执行完毕就立即返回了
shutDownNow调度器不会再接收新的任务,尝试关闭已经在执行的任务后再关闭调度器,但是不等待正在运行的任务执行完毕就立即返回,返回的是未执行的任务列表
awaitTermination阻塞等待所有任务执行完毕后返回,这个方法在shutDown或shutDownNow先执行后再执行
isShutDown判断调度器是否关闭
isTerminated判断调度器在关闭后所有任务是否都执行完毕,这个方法只在shutDown或shutDownNow执行完毕后才有可能返回true

AbstractExecutorService

在这里插入图片描述
AbstractExecutorService是一个实现了ExecutorService的抽象类,从上图它实现的方法我们就可以知道,这个类提供了调度器如何调度任务的默认实现。我们先来看下最简单的调度方法submit的默认实现:

Future<?> submit(Runnable task)

        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;

可以看到task被重新封装成RunnableFuture对象后再被执行,核心代码是第二行,我们来看下具体的代码

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

好吧,只是简单的构造一个FutureTask对象后直接返回,没啥好说的,其它的submit调度方法也跟它差不多

List<Future> invokeAll(Collection<? extends Callable> tasks)

if (tasks == null)
            throw new NullPointerException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks) {
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }

整个逻辑为:先执行所有任务,在等待所有任务执行完毕再返回。

List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)


        if (tasks == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));

            final long deadline = System.nanoTime() + nanos;
            final int size = futures.size();

            // Interleave time checks and calls to execute in case
            // executor doesn't have any/much parallelism.
            for (int i = 0; i < size; i++) {
                execute((Runnable)futures.get(i));
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L)
                    return futures;
            }

            for (int i = 0; i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    if (nanos <= 0L)
                        return futures;
                    try {
                        f.get(nanos, TimeUnit.NANOSECONDS);
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }

加上了一个超时判断,如果超时就立即返回

T invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

return doInvokeAny(tasks, true, unit.toNanos(timeout));

好吧,我们直接看doInvokeAny方法就行。。。


        if (tasks == null)
            throw new NullPointerException();
        int ntasks = tasks.size();
        if (ntasks == 0)
            throw new IllegalArgumentException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // Start one task for sure; the rest incrementally
            futures.add(ecs.submit(it.next()));
            --ntasks;
            int active = 1;

            for (;;) {
                Future<T> f = ecs.poll();
                if (f == null) {
                    if (ntasks > 0) {
                        --ntasks;
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    else if (active == 0)
                        break;
                    else if (timed) {
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                if (f != null) {
                    --active;
                    try {
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }

逻辑如图:
在这里插入图片描述

ThreadPoolExecutor

分析完顶层类的代码,这个类就很好分析了,因为源代码也就2000来行~
我们先来看下最丰富的构造方法

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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

结合这些参数,我们先来安利一波线程池的工作流程然后在分析源码。
当我们通过调度方法(submit/invokeAll/invokeAny/execute)执行任务时,线程池的处理逻辑如下,假设当前吃中线程的数量为T,workQueue中任务的数量为W,workQueue的容量为C:

条件说明工作方式
T < corePoolSize线程数小于corePoolSize创建一个新线程去执行任务,就算池中还有空闲的线程
T = corePoolSize && W < C线程数等于corePoolSize将任务存入workQueue队列,直到队列满
T < maximumPoolSize && W = C队列已满时创建一个新线程,直到线程数等于maximumPoolSize
T = maximumPoolSize && W = C线程数等于maximumPoolSize且队列已满执行RejectedExecutionHandler

我们注意到构造函数的参数中有一个keepAliveTime ,这个参数的作用是当线程数大于corePoolSize时,多余的线程如果空闲时间超过keepAliveTime,则线程被回收,所以我们可以知道线程预热一段时间后线程池中最小的线程数是corePoolSize

线程在workQueue的类型不同时,工作方式也会有不同

队列工作方式
SynchronousQueue任务永远不会存储这个队列中,队列将任务直接传递给线程,使用这个队列我们一般将maximumPoolSizes设置为无限Integer.MAX_VALUE,如果线程数设置的过小,当任务的生产大于消费的速度多余的任务肯定会被拒绝,如果线程数设置的过大,当任务的生产远远大于消费的速度时,线程会增长到一个很大的数值,所以这个队列需要谨慎使用
LinkedBlockingQueue如果构造这个队列的参数值为Integer.MAX_VALU,则这个队列就是无界队列,当线程数达到corePoolSize时且没有线程空闲时任务就会被存放在队列中,当任务的生产远远大于消费的速度时,队列中的任务数就会很大
ArrayBlockingQueue有界队列,可以控制系统资源的消耗,但是如果队列大线程少,虽然可以减少系统资源的使用但是也会导致任务吞吐量的降低,如果队列小线程大,会使系统资源繁忙的同时也有可能导致任务吞吐量降低,比如在线程上下文切换过于频繁的情况下

ok,我们现在再来看代码,我们知道AbstractExecutorService调度方法执行时都会默认调用execute方法,所以我们以executor为入口来法分析代码,我们先来分析下一些变量和内部类

	// runState(rs)指的是线程的运行状态
	// workCount(wc)指的是线程池中线程的数量
	//整数ctl(control),二进制表示总共是32位,这个变量高3位存储runState,低29位存储workCount
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    // 29,指的是wc的有效位数
    private static final int COUNT_BITS = Integer.SIZE - 3;
    // 1 << 29 = 001 000...(29个0)
    // (1 << 29) - 1 = 000 111...(29个1)
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // 下面五个变量定义线程池的运行状态runState
    // -1 << 29 = -001 000...(29个0)
    private static final int RUNNING    = -1 << COUNT_BITS;
    // 0 << 29 = 000 000...(29个0)
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // 1 << 29 = 001 000...(29个0)
    private static final int STOP       =  1 << COUNT_BITS;
    // 2 << 29 = 010 000...(29个0)
    private static final int TIDYING    =  2 << COUNT_BITS;
    // 3 << 29 = 011 000...(29个0)
    private static final int TERMINATED =  3 << COUNT_BITS;
    /**
    /* ~CAPACITY的值为111 000...(29个0),c & ~CAPACITY的意思其实就是将c的低
    /* 29位置0,高3位保留,因为c的高3位保存的是runState,所以计算的结果就是
    /* runState
    */
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    /**
    /* CAPACITY的值000 111...(29个1),c & CAPACITY的意思其实就是保留c的低
    /* 29位不变,高3位置0,因为c的低29位保存的workerCount,所以计算的结果就是
    /* workerCount,可见workerCount的最大值就是CAPACITY
    */
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    /** 
    /* rs肯定是*** 000...(29个0),wc肯定是000 ???(29位)
    /* rs | wc = *** ???(29位),相当于把rs保存在整数的高3位,
    /* wc保存在整数的低29位
    */
    private static int ctlOf(int rs, int wc) { return rs | wc; }

我们来看下每个rs下线程池的处理逻辑

rs说明
RUNNING线程池接受新的任务,运行队列中的任务
SHUTDOWN线程池不接受新的任务,但是仍会运行队列中的任务
STOP线程池不接受新的任务,不会运行队列中的任务,打断正在运行中的任务
TIDYING所以任务都终止了,wc == 0,线程池一旦到达这个状态,就会执行terminated()
TERMINATEDterminated执行完毕

线程池在设计rs的时候,它们的值有以下特点
RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED
线程池的rs变换也有这个特点:rs只能单调自增,但是不一定会经历每一个阶段。

状态转换触发条件
RUNNING -> SHUTDOWNshutdown()
(RUNNING or SHUTDOWN) -> STOPshutdownNow()
SHUTDOWN -> TIDYING线程池和队列都空了
STOP -> TIDYING当线程池空了
TIDYING -> TERMINATEDterminated()执行完

如何递增rs,线程池还专门提供了一个方法

    private void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            /**
            /* runStateAtLeast(c, targetState) 返回true 表明rs已经比targetState大了,不需要再自增,
            /* 为啥第一个参数是c,而不是runStateOf(c)呢?
            /* 因为rs在c的高3位,当c.rs != targetState比较大小只取决于高3位
            /* 当c.rs == targetState时,c肯定大于等于targetState
            /* 所以这个就可以节省一次方法调用
            /* ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))) CAS设置rs,如果失败,说明存在并发,则继续自旋
            */
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }
	// 顾名思义,检查s的值至少是c
    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }

其实所谓线程池中存储的并不是Thread,而是Worker,我们一般称之为工作线程,在线程池中用一个Set存储

	/**
     * Set containing all worker threads in pool. Accessed only when
     * holding mainLock.
     */
    private final HashSet<Worker> workers = new HashSet<Worker>();
	/**
	/* 这是线程池中实际存储的对象,封装了线程和任务,可以统计线程总共执行了多少任务
	/* 继承AQS的并实现了独占模式,是一个不可重入的锁
	/* 这个类中的方法还可以用来控制工作线程的执行。可以中断由于空闲一直在等待任务的
	/* 工作线程,而不影响已经在执行任务的工作线程(请看shutdown().interruptIdleWorkers()中的解释).
	*/
    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) {
        	/**
        	/* 在任务开始前,防止任务被中断,
        	/* 因为interruptIdleWorkers方法在中
        	/* 断任务的时候,
        	/* 会先trylock()获取锁,state == -1 trylock就失败了
        	*/
            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;
        }

		// Worker执行任务的时候需要先获取锁
        public void lock()        { acquire(1); }
        // 尝试获取锁,成功说明worker还未开始执行任务,state == 0,处于可以中断的状态,
        // 失败说明worker已经在执行任务了state == 1,或者处于禁止中断的状态state == -1
        public boolean tryLock()  { return tryAcquire(1); }
        // 释放锁
        public void unlock()      { release(1); }
        // 锁是否被持有,true表示worker开始执行任务了
        public boolean isLocked() { return isHeldExclusively(); }

		// 如果worker可以中断(state != -1),则中断线程
        void interruptIfStarted() {
            Thread t;
            // getState() >= 0 worker处于非禁止中断状态
            // (t = thread) != null 说明ThreadFactory创建线程成功,
            // ThreadFactory创建线程失败会返回null
            // !t.isInterrupted()线程还没有被中断
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }

我们不着急分析execute方法,因为调用链比较深,很多条件判断让人不明所以,我们现在看下shutdown

	/**
	/* 停止线程池,对已经运行的任务没有影响,线程池不再接受新的任务
	/* 但是线程池会继续处理队列中的任务,这个方法不会等待任务执行,而是立即返回
	/* 线程池状态变更为SHUTDOWN
	*/
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	// 检查权限,无视它。。。
            checkShutdownAccess();
            // 更改状态为SHUTDOWN
            advanceRunState(SHUTDOWN);
            // 中断空闲的工作线程,空闲线程指的是一直等待任务的线程
            interruptIdleWorkers();
            // 空的方法,需要子类实现
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }
    void onShutdown() {
    }

可以看到shutdown(),会将线程的状态更改为SHUTDOWN。

    private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }
	/**
	/* 中断空闲的工作线程,如果中断成功,每个线程在退出时
	/* 都会传播中断信号(传播的代码在runWorker().processWorkerExit()),
	/* 以便检测线程池是否可以关闭(状态rs向TERMINATED靠近,)
	*/
    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                /**
                /* !t.isInterrupted() 线程未中断。
                /* w.tryLock()成功说明w未执行任务(空闲)且处于可以中断的状态。
                /*
                /* runWorker()时候如果没有可以执行的任务,w会一直等待任务,此
                /* 时state == 0,runWorker()在自旋执行getTask()时如果检测
                /* 到中断信号就会结束等待退出线程;
                /*
                /* runWorker()时有可以执行的任务,会w.lock加锁,任务开始执
                /* 行后就可以保证如果此时执行shutdown()尝试获取锁肯定失败,
                /* 这样已经在执行的任务就不会被中断。
                /* 这也是Worker类上的英文注释为啥那么bb的原因
                */
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }
	/**
	/* 停止线程池,线程池不再接受新的任务,中断所有线程(包括空闲非空闲的)
	/* java中的所谓中断,其实都是发送一个中断信号给线程,线程响应不响应这个
	/* 信号没有保证,因为任务是我们编码提供的,对于正在执行中的任务所以如果需要响应中断的话,
	/* 得自己编写相关代码。
	/* 这个方法不会等待任务执行完,而是立即返回,因为所有线程都中断了
	/* ,所以会清空任务队列并返回这些任务
	/* 线程池状态变更为STOP
	*/
    public List<Runnable> shutdownNow() {
        List<Runnable> tasks;	
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	// 检查权限,无视它。。。
            checkShutdownAccess();
            // 更改状态为STOP
            advanceRunState(STOP);
            // 中断所有可以中断的任务
            interruptWorkers();
            // 清空任务队列并返回这些任务
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

	/**
	/* 中断所有可以中断的任务,只要state != -1。
	/* ,如果中断成功,每个线程在退出时都会
	/* 传播中断信号(会执行runWorker().processWorkerExit().tryTerminate()),
	/* 以便检测线程池是否可以关闭(状态rs向TERMINATED靠近)
	
	/* 对于state == -1的线程是没法中断的,此时分为两种情况:
	/* 1、任务队列不为空,此时线程池的状态是STOP了,这些线程监测到这个状态,会自己中断自己(看runWorker中的说明)
	/* 2、任务队列为空,runWorker时工作线程会一直等待任务
	/* 所以shutdownNow也是无法保证所有线程都是关闭的
	/* ,这也是为啥工作线程在退出时会tryTerminate会传播中断信号的原因之一。
	*/
    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                w.interruptIfStarted();
        } finally {
            mainLock.unlock();
        }
    }
	/**
	/* 將任务队列中的任务移入到list中并返回,同时将任务队列清空
	/* 很简单,我就不多bb了
	*/
    private List<Runnable> drainQueue() {
        BlockingQueue<Runnable> q = workQueue;
        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
        q.drainTo(taskList);
        if (!q.isEmpty()) {
            for (Runnable r : q.toArray(new Runnable[0])) {
                if (q.remove(r))
                    taskList.add(r);
            }
        }
        return taskList;
    }
	/** 
	/* 任何可能导致线程池状态走向TERMINATED的方法(满足工作线程减少)都需要执行这个方法。
	/* shutdown和shutdownNow方法都是用来终止线程池的,区别在于:
	/* 1、shutdown只关闭空闲线程,不会清空任务队列中的任务,同时可能还会有活跃的线程
	/* 2、shutdownNow关闭了所以能关闭的线程(可能有些线程处于未关闭状态),
	/* 同时任务队列会被清空
	*/
    final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            /**
            /* isRunning(c) 说明 rs == RUNNING; or
            /* runStateAtLeast(c, TIDYING)说明rs = TIDYING/TERMINATED; or
            /* (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())说明rs == SHUTDOWN 但是任务队列不为空
            /* 总结下意思是满足(rs == SHUTDOWN && workQueue.isEmpty) || 
            /* (rs == STOP)就往下走
            /* 为啥TIDYING不能往下走呢?
            /* 因为rs一到TIDYING会立即执行terminated(),执行完后状态立马更改为TERMINATED
            */
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            // wc != 0,说明可能还有线程空闲,中断一个空闲线程,以便传播中断信号
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
            	/**
            	/* 走着这里说明
            	/* ((rs == SHUTDOWN && workQueue.isEmpty) || rs == STOP) &&
            	/* wc == 0
            	/* 完美满足TIDYING的条件
            	*/
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                    	// 默认是个空方法,需要子类实现
                        terminated();
                    } finally {
                    	// rs = TERMINATED,wc =0
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

// 默认实现为空
protected void terminated() { }

我们再回过头看execute方法,这时候就一路了然了。

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        // wc < corePoolSize
        if (workerCountOf(c) < corePoolSize) {
        	// 创建worker执行任务
            if (addWorker(command, true))
                return;
			// addWorker失败
            c = ctl.get();
        }
        // 走到这里说明wc > corePoolSize
        // 将任务存放在任务队列
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 线程池终止不再接收新的任务
            if (! isRunning(recheck) && remove(command))
            	// 任务无法执行被拒绝
                reject(command);
            // wc == 0,池中没有线程了,创建任务线程执行任务队列中的任务    
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 工作队列已满,创建工作线程执行任务
        else if (!addWorker(command, false))
        	// 任务无法执行被拒绝
            reject(command);
    }

	/**
	/* 创建工作线程,并启动工作线程执行任务,工作线程会不停轮训,如果空闲,会等待任务
	/* firstTask:工作线程第一个执行的任务,等于null的话,工作线程会去任务队列取任务
	/* core:任务队列有界时,用来控制工作线程的最大数,是corePoolSize还是maximumPoolSize
	*/
    private boolean addWorker(Runnable firstTask, boolean core) {
    	// retry循环的作用是将判断能否添加worker,如果可以wc + 1
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
            
			/**
			/* rs >= SHUTDOWN 线程池不再接受新的任务。
			/*
			/* a = (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())
			/* 意思是 SHUTDOWN后任务队列可能不为空,如果firstTask == null的话,允许创建
			/* 一个新的worker去任务队列获取任务执行
			/* (查看runWorker中的while循环就知道是啥意思了)
			*/ 
            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;
                // addWorker没有加锁控制,并发addWorker CAS可能会失败,需要自旋  
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                // rs发生变化,可能被shutdown或者晋升到shutdown以后的状态,
                // 自旋转再次检查状态
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

		// 创建worker并把worker存入线程池,启动worker执行任务
        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());
					// 1、RUNNING
					// 2、SHUTDOWN, 需要去处理任务队列中的任务
					// retry已经检查过一次了,这里再次判断的原因是:retry循环未加锁,执行完后rs可能改变了
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        // 自定义ThreadFactory的时候,不要启动线程,不然就挂了
                        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的runnable是worker,t.start()调用的是worker.run(),最终调用的是runWorker
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

	/**
	/* 如果启动工作线程失败,需要做三件事
	/* 1、从线程池移除这个工作线程
	/* 2、wc--
	/* 3、尝试终止线程池
	/* 很简单,不多bb
	*/
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            decrementWorkerCount();
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }
    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        // 如果w还没执行到这里,shutdownNow和shutdown的时候w就不会收到中断信号
        w.unlock(); // allow interrupts
        // 是否异常
        boolean completedAbruptly = true;
        try {
        	// getTask从队列中获取任务
        	// 如果没有任务,会一直等待任务,(rs == SHUTDOWN+)时遇到中断就退出线程
        	// 如果有任务,执行任务
            while (task != null || (task = getTask()) != null) {
                w.lock();
                /**
                /* STOP后不再执行任务
                /* 这里的判断是为了中断那些shutdownNow后未中断的线程
                /*
                /* (rs >= STOP || (Thread.interrupted() && rs >= STOP))的意思是
                /* 1、rs >= STOP 如果未中断就中断
                /* 2、rs < STOP 清除中断信号
                /* 
                */
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                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();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

runWorker中的while是执行任务的主要流程,执行流程为:
beforeExecute -> task.run -> afterExecute
子类可以重写beforeExecute 和afterExecute方法,因为afterExecute在finally代码块中所以期间产生的任何Throwable 都会传递给afterExecute

runWorker执行的任务,要么是worker.firstTask,如果该任务为null或者已经执行完,那么就会尝试从队列中获取

	/**
	/* 从任务队列中获取任务
	/* 线程池的keepAliveTime线程空闲超时退出机制,使用队列的超时pool方法来实现
	/* 线程空闲会一直尝试获取任务,如果超过keepAliveTime还未成功就退出
	*/
    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            /**
            /* rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty()) ==
            /* 1、rs >= STOP 说明执行过shutdownNow了,任务队列肯定会空 ||
            /* 2、rs >= SHUTDOWN && workQueue.isEmpty() 执行过shutdown/shutdownNow了,
            /* 且任务队列已经空了
            */
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // 需要将超时线程退出
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

			/**
			/* wc > maximumPoolSize 说明调用了setMaximumPoolSizemaximumPoolSize,
			/* 新的值比旧的值小
			/* timed && timedOut 获取任务超时
			/* (wc > 1 || workQueue.isEmpty()) ==
			/* !(wc = 0 && !workQueue.isEmpty()) 意思是如果任务队列不是空的
			/* ,起码要有一个线程来处理任务
			*/
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                // wc--
                // CAS失败,说明存在并发,需要自旋重新检查条件
                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;
            }
        }
    }

runWorker如果任务执行期间有任何异常都会传播给finally代码块中的processWorkerExit方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
		// 由于发送异常造成的退出
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

		// 线程退出,从线程池中移除
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

		// 传播中断信号,rs尝试向TERMINATED晋升
        tryTerminate();

        int c = ctl.get();
        // rs == RUNNING or SHUTDOWN
        if (runStateLessThan(c, STOP)) {
        	// 正常退出
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                // 队列不为空,线程池中不能没有线程
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                // 工作线程数数量满足要求,方法直接返回
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            // 异常退出,创建一个新线程处理任务队列中的任务
            // 正常退出,线程数量少于最低要求,就创建一个新线程处理任务队列中的任务    
            addWorker(null, false);
        }
    }
	// c < s 返回true
    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }
	// 任务被拒绝
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

线程池由于任务队列已满或者线程已达最大值都有可能拒绝任务,线程池提供了有几种策略

策略说明
AbortPolicy默认的策略,直接抛出RejectedExecutionException
CallerRunsPolicy如果线程池还是RUNNING,直接由当前线程执行这个任务,这回导致线程池处理接收任务的速度变慢
DiscardPolicy直接丢弃任务
DiscardOldestPolicy如果线程池还是RUNNING,将任务队列头部的任务丢弃,再尝试提交这个任务

我们自己也可以实现RejectedExecutionHandler,这里不再多言。

除了execute、shutdown、shutdownNow这些线程调度方法外,线程池还提供了其它几类方法
,实现都非常简单,就不多bb了

类型方法
线程调度execute、shutdown、shutdownNow、invokeAll、invokeAny、submit、beforeExecute、afterExecute、onShutdown、awaitTermination、prestartAllCoreThreads、prestartCoreThread、purge、remove
动态配置setCorePoolSize、setKeepAliveTime、setMaximumPoolSize、setThreadFactory、setThreadFactory、allowCoreThreadTimeOut
获取配置信息getCorePoolSize、getKeepAliveTime、getMaximumPoolSize、getQueue、getRejectedExecutionHandler、getThreadFactory、allowsCoreThreadTimeOut
统计getActiveCount、getCompletedTaskCount、getLargestPoolSize、getPoolSize、getTaskCount
状态分析isShutdown、isTerminated、isTerminating
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值