线程池源码分析之ThreadPoolExecutor

先看ThreadPoolExecutor的类型继承图

接口Executor只有一个execute方法,方法里接受Runnable对象
void execute(Runnable command);

在看接口ExecutorService,该接口继承Executor接口。在Executor基础上添加了以下方法

主要添加关闭线程池,提交任务,获取关闭状,提交任务,执行任务的系列方法

AbstractExecutorService类实现了接口ExecutorService,该类是一个抽象了类添加了新建一个有返回值和没有返回值的任务的方法newTaskFor,实现了ExecutorService的提交任务和执行任务系列方法。下面看这些方法的具体实现
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();//判断任务是否为空
        RunnableFuture<Void> ftask = newTaskFor(task, null);//新建一个future任务
        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);

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

其中一系列doInvokerAny最终调用了submit方法,只是可以设置超时时间,如果超时则抛异常并取消正在执行的任务

我们继续看具体实现类ThreadPoolExecutor

ThreadPoolExecutor有状态RUNNING,SHUTDOWMN,STOP,TYDYING,TERMINATED

RUNNING:可以接受新任务并且处理队列里面的任务

SHUTDOWMN:可以处理队列里面的任务,不能接受新任务

STOP:不能接受任务也不能处理队列里的任务

TYDYING:所有任务都已终止,WorkerCount为零,线程转换为状态TYDYING将运行终止的terminated()钩子方法

TERMINATED:terminated()钩子方法已经运行完成

内部类Worker

 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) {//构造函数调用ExecutorPoolService的ThreadFactory生产线程
            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类实现类同步器和Runnable接口,AQS同步器其实就是维护一个int的状态执行的时候cas该状态值,如果cas成功则表示可以获取执行权限,否则加入到队列里面,以后的章节在分析AQS的源码,Worker的有成员变量thread和firstTask,thread是创建Worker的时候调用ExecutorPoolService的ThreadFactory生成的。run方法则执行ExecutorPoolService的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();//Worker实现了AQS同步器
              
                //如果池正在停止,请确保线程被中断;如果没有,确保线程不被中断。 这个
                 // 需要在第二种情况下重新检查才能处理 shutdownNow在清除中断时进行比赛
                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);
        }
    }

上面代码可知提交一个任务直接或者间接会调用execute方法,现在我们看看execute方法

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
       
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {//1:小于核心线程大小,尝试开启一个线程根据给定的command作为第一个task,这里的线程是核心线程
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {//2:任务直接添加到队列,这里正在运行的线程已经大于等于核心线程数
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))//3:和步骤一一样只是这样是非核心线程
            reject(command);//不成功则调用拒绝策略
    }

 

   提交一个任务大体执行步骤如下

  1. 先检查一下正在运行的线程数是否等于核心线程数,没有则创建一个核心线程并组装成Worker
  2. 否则直接添加到队列里面
  3. 否则创建一个非核心线程并组装成worker
  4. 调用给定的拒绝策略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值