JDK源码阅读(十):Executors和线程池

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aimomo007/article/details/89356937

线程池框架结构

线程池继承结构

Executor和ExecutorService

Executor和Executor Service

Executor作为顶层接口,仅仅提供了一个抽象的execute()方法,具体的实现交给了底层。分别有ThreadPoolExecutor、ScheduledThreadPoolExecutor和ForkJoinPool。

ExecutorService接口中定义子类公用的一些抽象方法定义

AbstractExecutorService

AbstractExecutorService实现了ExecutorService的定义的一些接口的实现方式,采用模板方法模式提供了submit()方法的算法骨架,然后由子类调用具体的execute()方法

submit

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

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;
}

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

ExecutorService类提供了三个submit方法,主要是创建RunnableFuture对象

newTaskFor

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

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

这个方法主要是创建了FutureTask类的实例,然后调用execute方法时,调用的就是FutureTask,具体的见后面executor方法的介绍

ThreadPoolExecutor

ThreadPoolExecutor构造函数

ThreadPoolExecutor提供了线程池的基本实现,如上图,它提供了4个不同参数的构造函数,如果用户未自定义就采用默认的参数,因此直接看最基础的构造函数,源码如下。

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;
    }

参数解释:

int corePoolSize :核心线程数
int maximumPoolSize :最大线程数
long keepAliveTime :存活时间
TimeUnit unit :存活时间单位
BlockingQueue workQueue :工作队列
ThreadFactory threadFactory :线程工厂
RejectedExecutionHandler handler:拒绝策略

Executors中的默认实现

Java中通过Executors类提供了一些线程池的默认实现,newSingleThreadExecutor、newFixedThreadEcecutor和newCachedThreadPool。

newSingleThreadExecutor

从源码中可以看出,这是提供了一个corePoolSize和maximumPoolSize都为1的线程池,即单线程。

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
    
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

newFixedThreadPool

从源码中可以看出,这是提供了一个统一设置corePoolSize和maximumPoolSize的线程池,即提供了一个固定线程的线程池。

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newCachedThreadPool

从源码中可以看出,这是提供了一个corePoolSize为0,maximumPoolSize不限制(理论上)的线程池,且线程的存活时间为60s,与上述两个线程池不一样的是它的工作队列采用了SynchronousQueue。

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }
    
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

execute

//采用一个AtomicInteger去存储线程池的状态和当前线程池中正在运行的线程的数量
//因为要存储两个变量,Integer是32位,因此将其一分为二,其中高3位用于存储线程池的状态,剩下的29位用于存储正在运行的线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//可用来标识线程数的最大值,即逻辑上最大的线程数
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
//从ctl中取出线程池状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//从ctl中取出当前正在运行的线程数量
private static int workerCountOf(int c)  { return c & CAPACITY; }
//将线程池和正在运行的线程数量打包为一个整数
private static int ctlOf(int rs, int wc) { return rs | wc; }
//线程池状态
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;

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
    //返回当前线程池状态和正在运行的线程数量
        int c = ctl.get();
    //判断当前正在运行的线程数是否小于核心线程数
        if (workerCountOf(c) < corePoolSize) {
            //如果任务线程成功start()
            if (addWorker(command, true))
                return;
            //再次获得线程池状态和正在运行的线程数量
            c = ctl.get();
        }
    //判断线程池状态是否还在运行并且向工作队列中添加任务
        if (isRunning(c) && workQueue.offer(command)) {
            //再次检查Ctl
            int recheck = ctl.get();
            //如果线程池不在运行中,则将任务从队列中移除,并尝试关闭线程池
            if (! isRunning(recheck) && remove(command))
                //根据拒绝策略拒绝这个任务
                reject(command);
            //如果正在运行的线程数为零
            else if (workerCountOf(recheck) == 0)
                //创建一个临时线程去阻塞队列中获取任务来执行。
                addWorker(null, false);
        }
    //如果线程状态不是RUNNING或者向队列中添加任务失败,再次尝试申请线程启动任务
        else if (!addWorker(command, false))
            //根据拒绝策略拒绝这任务
            reject(command);
    }

线程池具有以下五种状态,当创建一个线程池时初始化状态为RUNNING

线程池状态 描述
RUNNING 允许提交并处理任务
SHUTDOWN 不允许提交新的任务,但是会处理完已提交的任务
STOP 不允许提交新的任务,也不会处理阻塞队列中未执行的任务,并设置正在执行的线程的中断标志位
TIDYING 所有任务执行完毕,池中工作的线程数为0,等待执行terminated()勾子方法
TERMINATED terminated()勾子方法执行完毕

addWorker

private final HashSet<Worker> workers = new HashSet<Worker>();

//core用来标识使用corePoolSize判断还是maxinumPoolSize
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            // 线程池不是RUNNING状态且
            if (rs >= SHUTDOWN &&
                //线程池不是SHUTDOWN或者任务非空的或者工作队列是空的
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                //如果当前运行的线程数大于或者等于最大线程数
                if (wc >= CAPACITY ||
                    //或者大于指定值
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //通过CAS操作对正在运行的线程数+1,如果成功跳出循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                //重新获得线程池状态和正在运行的线程数
                c = ctl.get(); 
                //如果线程池状态改变了重新循环
                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 {
                    // 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;
    }

addWorkerFailed

//任务添加集合失败或者任务启动失败
private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                //从集合中移除任务
                workers.remove(w);
            //采用CAS对正在运行的线程数-1
            decrementWorkerCount();
            
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

tryTerminate

//尝试关闭线程池
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
        }
    }

reject

final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

拒绝策略

内置拒绝策略

RejectedExceptionHandler 特性及效果
AbortPolicy 线程池默认的策略,如果元素添加到线程池失败,会抛出RejectedExecutionException异常
DiscardPolicy 如果添加失败,则放弃,并且不会抛出任何异常
DiscardOldestPolicy 如果添加失败,会将队列中最早添加的元素移除,再尝试添加,如果失败则按该策略不断重试
CallerRunsPolicy 如果添加失败,那么主线程会自己调用执行器中的execute方法来执行任务

Worker

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);
        }

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

用户提交的任务并不是直接运行了然后封装了一层worker,真正启动的是Worker

runWorker

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();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    //可以重写该方法完成一些execute之前的操作
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        task.run();//真正的运行任务,调用run()方法,并未开始异步线程,start()方法才会开启异步线程
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        //可以重写该方法完成一些execute之后的操作
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

getTask

从阻塞队列中获取任务

//是否允许核心线程池超时
private volatile boolean allowCoreThreadTimeOut;

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.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // 是否允许核心线程池超时,或者当前运行的线程数大于核心线程数
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                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;
            }
        }
    }

FutureTask

在runWorker()方法中可以看到Worker线程去调用了任务的run()方法,对于FutureTask任务来说也是调用了它重写的run()方法。

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

在run()方法中调用了任务的call()方法,拿到返回结果

ScheduledExecutorsService

ScheduledExecutorService

ScheduledExecutorsService主要提供了创建定时任务的几种方式

ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor构造函数

ScheduledThreadPoolExecutor也是继承了ThreadPoolExecutor,但是在普通线程池的基础上提供了定时任务的功能。从下面的源码看出,它实际上也是调用了ThreadPoolExecutor的构造函数,提供了一个corePoolSize可设置,maximumPoolSize不限制(理论上)的线程池,定时任务的功能主要是通过DelayedWorkQueue队列实现。

public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }

Executors中的默认实现

Java中通过Executors类提供了定时任务线程池的默认实现,newScheduledThreadPool。

newScheduledThreadPool

从源码看出并没有额外功能的添加

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
    
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

ScheduledFutureTask

public void run() {
            boolean periodic = isPeriodic();
            if (!canRunInCurrentRunState(periodic))
                cancel(false);
            else if (!periodic)
                ScheduledFutureTask.super.run();
            else if (ScheduledFutureTask.super.runAndReset()) {
                setNextRunTime();
                reExecutePeriodic(outerTask);
            }
        }

与FutureTask一样,ScheduledFutureTask的run执行业务逻辑以后 将重新计算对象的 delay 时间,再通过 runAndReset 方法将重新计算的后的对象重置回工作任务阻塞队列中。由于默认实现的 compareTo 方法,这样,就实现了线程周期性的执行任务的功能。

ForkJoinPool

这是在1.7中新增的一个采用forkjoin模式处理任务的线程池,比较特殊。

public ForkJoinPool(int parallelism,
                        ForkJoinWorkerThreadFactory factory,
                        UncaughtExceptionHandler handler,
                        boolean asyncMode) {
        this(checkParallelism(parallelism),
             checkFactory(factory),
             handler,
             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
             "ForkJoinPool-" + nextPoolId() + "-worker-");
        checkPermission();
    }

newWorkStealingPool

public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

参考链接:fork-join模型介绍

猜你喜欢

转载自blog.csdn.net/aimomo007/article/details/89356937