线程池-百战将军尤在马

2019-10-04  本文已影响0人  江北晓白

上一个分享中,对线程进行了刨析,因为线程申请和释放,会调用本地native方法,调用liunx的方法进行上下文切换并申请和释放资源。所以采用线程池可以减少这种资源的申请和释放,提高系统的性能。
本章对线程池的池化技术进行刨析。
一、温酒


从图中可以看出,ThreadPoolExecutor继承了AbstractExecutorService这个抽象类,该类实现了ExecutorService,ExecutorService继承了Executor接口。
Exexcutor接口只有一个execute接口,线程池主要依赖于该接口提交线程。

public interface Executor {
    void execute(Runnable command);
}

ExecutorService接口主要提供了submit接口:

    void shutdown();
    List<Runnable> shutdownNow();
    boolean isShutdown();
    boolean isTerminated();
    boolean awaitTermination(long timeout, TimeUnit unit)
    <T> Future<T> submit(Runnable task, T result);
    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)
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)

AbstractExecutorService这个抽象类主要实现了submit方法和invokeAny方法。

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

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

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

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

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

ThreadPoolExecutor继承了AbstractExecutorService这个抽象类,AbstractExecutorService、Excutor提供了Pool基本的执行能力。
二、跨马
1、线程状态参数
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
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;
通过打印:



线程池中线程的工作状态用int的高三位表示,从上面的二进制中可以知道,当线程为RUNNING态时,其值<0,其他状态均>0。
2、构造函数

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);//保活时间,unit时间单位
        this.threadFactory = threadFactory;//线程工厂
        this.handler = handler;//拒绝策略
    }

1)默认参数
线程工厂:默认线程工厂如下。

DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

拒绝策略:拒绝策略一共有四种,默认策略为AbortPolicy()

 private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

其他几种策略源码如下():

//CallerRunsPolicy策略调用deamon线程执行请求任务run方法
 public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
//AbortPolicy策略直接拒绝请求抛出异常
    public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
//DiscardPolicy策略拒绝请求,不抛出异常
    public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
//DiscardOldestPolicy策略将队列头的任务释放,将任务放入队列中
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
}

3)默认线程池Excutors

//LinkedBlockingQueue阻塞队列是无限扩容的队列
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
//SynchronousQueue队列是互斥队列,newCachedThreadPool线程池每次请求新建线程,如果该线程<60s未处于空闲状态,则新来请求可以复用未销毁线程来执行任务
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
//newSingleThreadScheduledExecutor 线程池可以作为定时器使用
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

三、回首望京阙
ThreadPoolExecutor组合了ReentrantLock(重入锁)、Condition(状态量)、works(继承了AQS,实现了Runnable接口的线程集合,works继承关系入下图):

private final ReentrantLock mainLock = new ReentrantLock();
private final HashSet<Worker> workers = new HashSet<Worker>();
private final Condition termination = mainLock.newCondition();

上面大量的篇幅对ThreadPoolExecutor的基础进行了铺垫,下面就ThreadPoolExecutor的具体实现进行刨析。
前面分析过ThreadPoolExecutor类实现了Executor接口,该接口中只有一个方法execute,这是ThreadPoolExecutor的入口。

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        //获取线程池统计变量
---------------------------------------
 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
 private static int ctlOf(int rs, int wc) { return rs | wc; }
采用了32位的后29位作为统计works数
---------------------------------------
        int c = ctl.get();
        //如果works小于核心线程数
        if (workerCountOf(c) < corePoolSize) {
          //addWorker是实现将线程添加到works集合的入口,具体实现见下文
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //上面works大于核心线程数或者添加works失败,该线程是Running态,则将该请求放入任务队列中
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
          //重新判断当前线程池状态,如果是非运行态,此时线程池退出,则移除请求并拒绝请求
            if (! isRunning(recheck) && remove(command))
                reject(command);
            //当前工作线程数为0
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
//上述条件都不满足,则拒绝
        else if (!addWorker(command, false))
            reject(command);
    }

addWorker的实现如下:

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

            // 如果线程池状态为非Running态,且它不满足(Shutdown态,提交任务为null,任务队列非空)就返回false;看execute的实现中,这种状态下会拒绝任务。
----------------------------------------------------
//上述条件都不满足,则拒绝
        else if (!addWorker(command, false))//重试提交任务,失败则拒绝
            reject(command);
----------------------------------------------------
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
//通过for自旋来提交任务
            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
              //cas自增原子数,成功则进行addWorker下半部分,否则自旋
                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
            }
        }
//addWorker下半部分
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
           //新建线程对象
            w = new Worker(firstTask);//此处通过构造函数生成Worker对象w
--------------------------------------------
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }
 //Wroker实现了Runnable方法,该处run方法是Worker对象start后的执行方法入口
        public void run() {
            runWorker(this);
        }
——————--——————————————————————
//该方法就是把Worker中的firstTask任务执行其run方法
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;//前面《ThreadLocals因何而得藕》中,讲过线程池中线程复用,该处Worker线程执行完任务后没有销毁,而是将接收的firstTask=null,从而从任务队列中获取任务,见下面
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
 //getTask方法中获取可执行的任务
————————————————————————————
private Runnable getTask() {
        boolean timedOut = false; 
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
//获取阻塞线程任务时,如果线程池状态变更,减少works数量,同ad dWorker中的原子增正相反
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//超时且队列为null则尝试原子减
            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;
            }
        }
    }
————————————————————————————
//先执行Thread的firstTask任务,如果firstTask任务为null,则从任务队列中获取任务执行,getTask见上面。此处跟上面的firstTask=null呼应,通过此处理解ThreadLocal的使用的注意事项尤其重要。
            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 {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                      //这是其具体调用,参考上面的构造函数,task是请求的任务的Runnable实现
                        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);
        }
    }
————————————————————————————
--------------------------------------------
            final Thread t = w.thread;//这里线程t是Worker的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());
                    //判断线程池状态,向works添加线程
                    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;
    }

start方法是执行线程的启动方法:

public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        boolean started = false;
        try {
          //通过本地start0方法将新建的Worker启动
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

通过上面分析,可以知道,线程池启动的是其Worker线程资源,并执行Worker的run方法调用构造函数中传入的请求任务的Runnable接口的run方法来执行任务。
execute方法是无返回值的方法,ThreadPoolExecutor还有一种有返回值的提交任务的方法,叫submit方法,如下:

 public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
//RunnableFuture 通过构造函数封装了Callable的任务,具体实现见下面
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
---------------------------------------------------
public interface Callable<V> {
    V call() throws Exception;
}
————————————————————————
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
 public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
——————————————————-——————
//该run方法是RunnableFuture的run方法,通过该run方法执行Callable任务的call方法,并将返回值通过该RunnableFuture返回
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);
        }
    }
---------------------------------------------------

四、后记:
百战将军尤在马,回首望,遍地狼烟秋风起,恍恍惚惚好河山。

上一篇下一篇

猜你喜欢

热点阅读