java并发编程(2):ThreadPoolExecutor源码详解

ThreadPoolExecutor的继承结构如下:

9795603-e970dc3836d89567.png
ThreadPoolExecutor继承结构.png

1、ExecutorService及AbstractExecutorService源码解析

1.1、ExecutorService接口

ExecutorService定义了线程终止、任务提交相关的接口。

public interface ExecutorService extends Executor {
    
    // 平滑关闭线程池,当此方法被调用时,ExecutorService 将停止接受新的任务,
    // 并等待已经提交的任务执行完成。当所有任务执行完毕,线程即被关闭
    void shutdown();
    
   
    // 停止所有在执行中的任务,返回等待被执行任务的list 
    List<Runnable> shutdownNow();

    //线程池是否已经关闭
    boolean isShutdown();

    //所有的任务是否已被终止,只有shutdown或shutdownNow被调用后,此方法才可能返回true
    boolean isTerminated();

    //在设定的超时时间内等待线程池关闭
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

    //提交Callable类型的任务
    <T> Future<T> submit(Callable<T> task);

   
   //提交Runnable类型的任务,默认返回类型为result
    <T> Future<T> submit(Runnable task, T result);

    //提交Runnable类型的任务
    Future<?> submit(Runnable task);

    //提交多个任务,并等待所有的任务执行完成
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

    //提交多个任务,并在设定的超时时间内等待任务执行完成
    //超时后,任务未完成的任务都会被取消
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

    //提交多个任务,若有任何一个任务执行成功,则返回执行成功的任务结果
    //并取消其他任务;若任务中无完成的,则或抛出异常。
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

   //在设定的超时时间内等待某人任务完成。
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

1.2、AbstractExecutorService抽象类

AbstractExecutorService是实现了ExecutorService接口的抽象类,其对通用的任务提交做了默认实现。

public abstract class AbstractExecutorService implements ExecutorService {

    //通过Runnable及value构造一个RunnableFuture对象
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    //通过Callable构造一个RunnableFuture对象
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    //提交一个Runnable任务到线程池执行
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        //将Runnable任务封装成RunnableFuture任务
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        //提交任务
        execute(ftask);
        return ftask;
    }

   //提交一个Runnable任务到线程池执行,默认返回值为result
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

    //提交一个Callable任务到线程池
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

    //获取多个提交的任务中,最早执行成功的返回结果
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        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);

        try {
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // 先提交一个任务,并将异步结果放到futures总
            futures.add(ecs.submit(it.next()));
            --ntasks;
            int active = 1;

            for (;;) {
                //获取异步任务的执行结果
                Future<T> f = ecs.poll();
                //结果为空,表示还未有任务执行完毕
                if (f == null) {
                    //继续提交任务,并将异步结果放当futures中
                    if (ntasks > 0) {
                        --ntasks;
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    //当所有任务都执行完毕,但任务执行异常,则直接退出循环
                    else if (active == 0)
                        break;
                   
                    //若任务全部提交完,并设置了超时时间,则通过poll+超时时间获取结果
                    //若超时还未获取到,则抛出TimeoutException()异常,否则继续超时等待
                    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);
        }
    }

    //获取多个提交的任务中,最早执行成功的返回结果
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
        try {
            return doInvokeAny(tasks, false, 0);
        } catch (TimeoutException cannotHappen) {
            assert false;
            return null;
        }
    }

    //在超时时间内,获取多个提交的任务中,最早执行成功的返回结果
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
    }

    //获取多个提交任务的所有执行结果
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        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);
        }
    }

    //在超时时间内,获取多个提交任务的所有执行结果
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        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();

            //提交所有任务
            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);
        }
    }

}

2、ThreadPoolExecutor源码解析

2.1、基本属性说明

//记录线程池的状态即线程数量,32位中,前三位表示线程池状态,后29位表示线程数量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程数量所占的bit位,共:Integer.SIZE - 3,即32-3=29位
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程的最大数量,即:000 11111111111111111111111111111,十进制为536870911个线程
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

//线程池状态:运行中(111 00000000000000000000000000000)
private static final int RUNNING    = -1 << COUNT_BITS;
//线程池状态:关闭 (000 00000000000000000000000000000)
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//线程池状态:停止 (001 00000000000000000000000000000)
private static final int STOP       =  1 << COUNT_BITS;
//线程池状态:清理 (010 00000000000000000000000000000)
private static final int TIDYING    =  2 << COUNT_BITS;
//线程池状态:终止 (011 00000000000000000000000000000)
private static final int TERMINATED =  3 << COUNT_BITS;

//通过ctl获取运行状态(获取前3位)
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//通过ctl获取线程个数(获取后29位)
private static int workerCountOf(int c)  { return c & CAPACITY; }
//通过线程数量及线程池状态合成ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }


//任务队列
private final BlockingQueue<Runnable> workQueue;

//同步锁
private final ReentrantLock mainLock = new ReentrantLock();

//worker线程集合
private final HashSet<Worker> workers = new HashSet<Worker>();

//信号量
private final Condition termination = mainLock.newCondition();

//工作线程的最大数量
private int largestPoolSize;

//已完成的任务计数
private long completedTaskCount;


//线程创建工厂
private volatile ThreadFactory threadFactory;

//线程池对拒绝的任务的处理
private volatile RejectedExecutionHandler handler;

//线程池中线程允许的最大空闲时间
private volatile long keepAliveTime;

//是否允许核心线程在空闲keepAliveTime时间后进行超时回收
private volatile boolean allowCoreThreadTimeOut;

//核心线程池数量
private volatile int corePoolSize;

//最大线程池数量
private volatile int maximumPoolSize;

2.2、线程池状态说明

//运行中 111 00000000000000000000000000000
private static final int RUNNING    = -1 << COUNT_BITS;
//关闭 000 00000000000000000000000000000
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//停止 001 00000000000000000000000000000
private static final int STOP       =  1 << COUNT_BITS;
//整理 010 00000000000000000000000000000
private static final int TIDYING    =  2 << COUNT_BITS;
//终止 011 00000000000000000000000000000
private static final int TERMINATED =  3 << COUNT_BITS;
  • RUNNING:接受新任务,处理阻塞队列里的任务
  • SHUTDOWN:拒绝接收新任务,但继续处理执行中及阻塞队列里的任务,并且会中断空闲的线程。在线程池出于RUNNING状态时,调用shutdown()方法会使线程池进入该状态。
  • STOP:拒绝接收新任务,并且抛弃阻塞队列里的任务,同时会中断线程池中的所有线程。在线程池处于RUNNING或SHUTDOWN状态时,调用shutdownNow()方法会使线程池进入该状态。
  • TIDYING:所有任务已终止,当前线程池活动线程为0,线程池进入该状态后会调用terminated()方法,然后让线程池进入TERMINATED状态。当线程池处于SHUTDOWM状态时,如果此后线程池内没有线程并且阻塞队列内没有待执行的任务,线程就会进入该状态。当线程池处于STOP状态时,若此后线程池内没有线程了,线程池也会进入该状态。
  • TERMINATED:终止状态。terminated()方法调用完成以后的状态.

状态转换:

9795603-3b73ed487d9b5cd0.png
状态转换.png

2.3、构造函数说明

ThreadPoolExecutor的构造方法中提供了几个非常重要的参数,这些参数对线程的创建、线程调度、阻塞队列等都有很大影响。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
  • corePoolSize:核心线程数量。核心线程即为从创建以后一直存活的线程,这些线程不会因为空闲太长时间而被回收。除非设置了allowCoreThreadTimeOut为true,即允许核心线程空闲超时时间而终止,使得存活的核心线程数量最终变为0。默认情况下,核心线程是按需创建的,即只有当线程池接收到任务时才会主动创建核心线程,否则不会主动创建线程。这有利于降低系统资源的消耗。当有特殊需求,如需要系统预热,需要预先创建将核心线程创建好,则可以通过prestartCoreThread()或prestartAllCoreThreads() 方法来预先创建一个或corePoolSize个核心核心线程,这样使得新任务提交到线程池的时候,可以立即有线程资源来处理新任务,而无需等待系统耗时创建新线程。
  • maximumPoolSize:线程池的最大线程数。maximumPoolSize <= CAPACITY (5亿多)。当我们通过方法 execute(Runnable) 提交一个任务到线程池时, 如果处于运行状态(RUNNING)的线程数量少于核心线程数(corePoolSize), 那么即使有一些非核心线程处于空闲等待状态, 系统也会倾向于创建一个新的线程来处理这个任务. 如果此时处于运行状态(RUNNING)的线程数量大于核心线程数(corePoolSize), 但又小于最大线程数(maximumPoolSize), 那么系统将会去判断线程池内部的阻塞队列 workQueue 中是否还有空位子. 如果发现有空位子, 系统就会将该任务先存入该阻塞队列; 如果发现队列中已没有空位子(即: 队列已满), 系统就会新创建一个线程来执行该任务。如果将线程池的核心线程数 corePoolSize 和 最大线程数 maximumPoolSize 设置为相同的数值(也就是说, 线程池中的所有线程都是核心线程), 那么该线程池就是一个容量固定的线程池. 如果将最大线程数 maximumPoolSize 设置为一个非常大的数值(例如: Integer.MAX_VALUE), 那么就相当于允许线程池自己在不同时段去动态调整参与并发的任务总数. 通常情况下, 核心线程数 corePoolSize 和 最大线程数 maximumPoolSize 仅在创建线程池的时候才去进行设定, 但是, 如果在线程池创建完成以后, 你又想去修改这两个字段的值, 你就可以调用 setCorePoolSize() 和 setMaximumPoolSize() 方法来分别重新设定核心线程数 corePoolSize 和 最大线程数 maximumPoolSize 的数值。
  • keepAliveTime:空闲线程的超时时间。即,当线程空闲时间超过这个时间,线程会终止。非核心线程空闲时间超过keepAliveTime时会终止,对于核心线程,当allowCoreThreadTimeOut 为false时,其不受allowCoreThreadTimeOut 影响,会一直存活;当allowCoreThreadTimeOut 为false时,其和非核心线程一样受超时影响。如果要执行的任务相对较多,并且每个任务执行的时间比较短,那么可以为该参数设置一个相对较大的数值,以提高线程的利用率。如果执行的任务相对较少, 线程池使用率相对较低, 那么可以先将该参数设置为一个较小的数值, 通过超时停止的机制来降低系统线程资源的开销, 后续如果发现线程池的使用率逐渐增高以后, 线程池会根据当前提交的任务数自动创建新的线程, 当然, 我们也可以自己手动调用 setKeepAliveTime(long, TimeUnit)方法来重新设定 keepAliveTime 字段的值.。
  • workQueue:BlockingQueue类型的阻塞队列。阻塞队列是一种类似于 “生产者 - 消费者”模型的队列. 当队列已满时如果继续向队列中插入元素, 该插入操作将被阻塞一直处于等待状态, 直到队列中有元素被移除产生空位子后, 才有可能执行这次插入操作; 当队列为空时如果继续执行元素的删除或获取操作, 该操作同样会被阻塞而进入等待状态, 直到队列中又有了该元素后, 才有可能执行该操作.

当提交一个新的任务到线程池以后, 线程池会根据当前池子中正在运行着的线程的数量, 指定出对该任务相应的处理方式, 主要有以下几种处理方式:

(1) 如果线程池中正在运行的线程数少于核心线程数, 那么线程池总是倾向于创建一个新线程来执行该任务, 而不是将该任务提交到该队列 workQueue 中进行等待.

(2) 如果线程池中正在运行的线程数不少于核心线程数, 那么线程池总是倾向于将该任务先提交到队列 workQueue 中先让其等待, 而不是创建一个新线程来执行该任务.

(3) 如果线程池中正在运行的线程数不少于核心线程数, 并且线程池中的阻塞队列也满了使得该任务入队失败, 那么线程池会去判断当前池子中运行的线程数是否已经等于了该线程池允许运行的最大线程数 maximumPoolSize. 如果发现已经等于了, 说明池子已满, 无法再继续创建新的线程了, 那么就会拒绝执行该任务. 如果发现运行的线程数小于池子允许的最大线程数, 那么就会创建一个线程(这里创建的线程是非核心线程)来执行该任务.

  • threadFactory:线程工厂,用于线程的创建。如果我们在创建线程池的时候未指定该 threadFactory 参数, 线程池则会使用 Executors.defaultThreadFactory() 方法创建默认的线程工厂. 如果我们想要为线程工厂创建的线程设置一些特殊的属性, 例如: 设置见名知意的名字, 设置特定的优先级等等, 那么我们就需要自己去实现 ThreadFactory 接口, 并在实现其抽象方法 newThread()的时候, 使用Thread类包含 threadName (线程名字)的那个构造方法就可以指定线程的名字(通常可以指定见名知意的名字), 还可以用 setPriority() 方法为线程设置特定的优先级等. 然后在创建线程池的时候, 将我们自己实现的 ThreadFactory 接口的实现类对象作为 threadFactory 参数的值传递给线程池的构造方法即可.

  • handler:线程池拒绝处理任务的处理。当线程池处于SHUTDOWN状态或线程池中所有线程都处于运行状态并且线程池的阻塞队列已满时,提交线程是会调用此对象的rejectedExecution()方法对任务进行处理。

2.4、RejectedExecutionHandler说明

RejectedExecutionHandler为拒绝处理任务的回调。当线程池处于SHUTDOWN状态或线程池中所有线程都处于运行状态并且线程池的阻塞队列已满时,提交线程是会调用此对象的RejectedExecutionHandler.rejectedExecution()方法对任务进行回调处理。

ThreadPoolExecutor中的RejectedExecutionHandler实现有以下几种:

  • CallerRunsPolicy:若线程池状态为RUNNING,则直接由提交任务的线程执行任务;否则不进行任何处理。
  • AbortPolicy:不论线程池处于什么状态,则直接抛出RejectedExecutionException异常。
  • DiscardPolicy:不对任务做任何处理。
  • DiscardOldestPolicy:移除线程池阻塞队列中最早的一个任务,并将当前任务添加到阻塞队列中。

2.5、BlockingQueue简要说明

BlockingQueue为阻塞队列,其利用同步锁实现线程安全地进行任务的入队与出队,同时利用信号量,实现线程之间的任务添加及等待的通知等。其主要作用是作为任务生产者和线程消费者的任务队列。

public interface BlockingQueue<E> extends Queue<E> {
    //将对象e添加到阻塞队列中,若添加成功,则返回true;否则抛出异常。
    //若空间已满,则会抛出IllegalStateException异常;
    //若e为null,则会抛出NEP异常;
    //若为其他原因,还会抛出其他如ClassCastException或IllegalArgumentException等
    boolean add(E e);

    //将对象e添加到阻塞队列中,若添加成功,则返回true;若空间不够,否则返回false。
    boolean offer(E e);

    //插入对象e到阻塞队列中,当队列有空间可以时,直接插入并返回true;
    //否则等待直到队列有空间可用;
    void put(E e) throws InterruptedException;

    //插入对象e到阻塞队列中,当队列有空间可以时,直接插入并返回true;
    //当队列空间不够时,阻塞等待,直到有空间可用或超时;
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

    //获取并移除队列头部元素,若队列为空,等待直到队列有元素可获取;
    E take() throws InterruptedException;

    //获取并移除队列头部元素,若队列为空,等待直到队列有元素可获取或超时;
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

    //获取队列中剩余空间,若队列长度无限制,返回为Integer.MAX_VALUE;
    //此方法获取的只是调用接口时的瞬时值,因为其他线程或向队列添加或移除元素;
    int remainingCapacity();

    //将对象o从队列中移除,若队列改变了,则返回true;否则返回false
    boolean remove(Object o);
    
    //若对象o存在于队列中,则返回true;否则返回false
    public boolean contains(Object o);
    
    //移除队列中的所有元素,并将它们添加到集合c中;
    //此操作比重复调用poll从队列中获取元素要高效
    //若在调用此方法时向队列中添加元素并抛出异常,则返回失败;
    //若在调用方法的时候更新了队列,则操作结果无法预料。
    int drainTo(Collection<? super E> c);
    
    //操作同上,而此方法只移除maxElements个元素;
    int drainTo(Collection<? super E> c, int maxElements);
}

2.6、Worker说明

Worker是ThreadPoolExecutor中对线程、同步锁及线程任务完成统计量的封装,其同时也是一个任务;

private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    //当前worker对应的线程实例
    final Thread thread;
    //woker的第一个任务。因线程池在创建worker的时候会带有任务
    Runnable firstTask;
    //完成的任务数
    volatile long completedTasks;

   
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

    //线程启动worker,worker不断从阻塞队列中获取任务并执行任务
    public void run() {
        runWorker(this);
    }

    //当前worker是否获取了独占锁
    protected boolean isHeldExclusively() {
        return getState() != 0;
    }

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

    //cas释放锁
    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(); }
    
    //中断当前worker,即中断当前线程
    void interruptIfStarted() {
        Thread t;
        //worker已经启动,并且线程不为空,并且线程未被中断
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                //中断线程
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}

runWorker()方法是Worker的任务处理核心,其先处理firstTask,然后会从循环从阻塞队列中获取任务,然后执行任务;

2.7、主要处理流程说明

2.7.1、任务添加处理

execute()处理流程:

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    //若线程池中当前线程数小于核心线程数,则直接创建一个worker,
    //并将当前任务作为worker的第一个任务;
    if (workerCountOf(c) < corePoolSize) {
        //addWorker()创建线程并执行任务,其中也会再次检查线程池状态即线程数量等信息;
        //若不满足创建线程的条件,则返回false;否则返回true,表示添加线程成功
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //线程池状态为运行状态,并且任务入队成功;
    if (isRunning(c) && workQueue.offer(command)) {
        //重新获取线程池状态即数量信息
        int recheck = ctl.get();
        //若线程池状态不为运行中,则移除任务,并调用reject进行拒绝任务处理;
        //此种情况发生为添加任务到阻塞队列后,线程池被SHUTDOWN
        if (! isRunning(recheck) && remove(command))
            reject(command);
        //线程池中线程数量为空?则创建一个worker线程处理任务
        //此种情况发生在核心线程数设置为0的时候    
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    //若线程池被关闭或任务队列已满时,会走到当前分支
    //此时会尝试向线程池中添加一个worker线程并执行任务;
    //而当线程池关闭或线程数量已经达到线程池容量时,无法创建worker线程,此时会返回false;则调用reject()进行拒绝任务处理
    //而若只是阻塞队列满了并且线程池线程数量也未达容量上线,则无法添加任务了,则创建线worker会成功,任务也会成功执行;
    else if (!addWorker(command, false))
        reject(command);
}

任务执行主要流程:

  • 若核心线程数量未达核心线程容量上限,则创建一个核心线程,并将当前任务作为核心线程的第一个任务。
  • 若阻塞队列未达容量上限,则将任务添加的阻塞队列中并等待某个线程调用处理;
  • 若线程数量未达线程池线程容量上限,则创建一个worker线程,并将当前任务作为worker线程的第一个任务。

addWorker()处理:

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

        //检查线程池状态,若线程池在以下两个状态时,直接返回false,不允许创建worker
        //1、若线程池状态为:STOP、TIDYING、TERMINATED状态
        //2、若线程池状态为:SHUTDOWN,当前添加的任务为空,阻塞队列非空;即线程池正在准备关闭处理。
        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
        }
    }

    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 {
                // 获取线程池状态
                int rs = runStateOf(ctl.get());
                
                //线程状态为小于SHUTDOWN,即为RUNNING状态
                //获取线程池状态为SHUTDOWN,并且当前添加的任务为空
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    //线程已经启动?  则抛出异常  
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    //向worker队列中添加worker
                    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;
}

2.7.2、任务运行处理

任务运行处理是在线程添加成功后,调用其对应的start()方法启动线程;线程启动后会运行Worker.run()方法,而其中实际调用的是runWorker()方法。

任务处理runWorker():

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); 
    boolean completedAbruptly = true;
    try {
        //若task不为空,即worker的第一个任务不为空;
        //或从队列中获取到任务
        while (task != null || (task = getTask()) != null) {
            w.lock();
            //若满足以下条件一种,则中断worker线程
            //1、线程池状态为:STOP或TIDYING或TERMINATED,而线程未中断;
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                //bufore执行任务
                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 {
                    //after执行任务
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

获取任务getTask():

private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

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

        // 若线程池状态为STOP,或状态为SHUTDOWN且阻塞队列为空;则减少线程数量
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);

        // 允许核心线程池空闲超时或当前线程数大于核心线程数容量
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
            
        //若获取任务超时,则减少worker数量   
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            //需要空闲超时判断处理,则调用带超时时间的pool获取任务;
            //否则调用take阻塞等待任务
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

2.7.3、线程池关闭处理

线程池的关闭主要有以下两种方法:shutdown()和shutdownNow();shutdown()会将线程池状态设置为SHUTDOWN,此状态下线程池不会接受新的任务,但会将正在执行和阻塞队列中的任务执行完成后再关闭,同时会中断空闲的线程;而shutdownNow()会将线程池状态设置为STOP,并返回阻塞队列中所有未执行的任务,同时中断所有线程,不论线程空闲与否;

线程关闭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();
}

线程关闭shutdownNow():

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        advanceRunState(STOP);
        //中断所有线程
        interruptWorkers();
        //移除等待队列中的任务
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    //做后续线程关闭工作
    tryTerminate();
    return tasks;
}

线程关闭处理:

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        //1、现在状态为RUNNING;
        //2、线程已经关闭完成;
        //3、线程状态为SHUTDOWN,且阻塞队列不为空;
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        //存活的线程数大于0?    
        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 {
                    //设置线程池状态为TERMINATED,表示线程池关闭完成
                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

线程添加失败时对线程池状态进行检查处理:

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

2.7.4、其他重要方法

方法名说明
isShutdown若线程池状态不为RUNNING,则返回true;否则为false
isTerminating若线程池状态为TERMINATED,则返回true;否则返回false
awaitTermination在超时时间内等待线程关闭完成
setCorePoolSize调整线程池核心线程数,可以比当前多也可以少
prestartCoreThread预创建一个核心线程
ensurePrestart预创建一个核心线程或普通线程
prestartAllCoreThreads预创建所有核心线程
allowsCoreThreadTimeOut设置运行核心线程空闲超时
setKeepAliveTime设置空闲超时时间
setMaximumPoolSize设置最大线程数
beforeExecute任务执行之前的钩子回调
afterExecute任务执行之后的钩子回调,不论正常或异常
terminated任务关闭完成的钩子回调
onShutdown线程池关闭的钩子函数,在shutdown()会调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值