源码解析 ThreadPoolExecutor JAVA1.8

1 篇文章 0 订阅

1. 构造函数

  • corePoolSize:池里维持的最小线程数,即使它们是空闲线程,也不会进行销毁
  • maximumPoolSize:最大线程数
  • keepAliveTime:当池里的线程数量超过了corePoolSize时,如果额外线程在keepAliveTime时间段内都未执行新任务,将被销毁
    • 核心线程和额外线程是明确区分的,核心线程一般不会被销毁
  • unit:keepAliveTime的时间单位
  • workQueue:存放被执行任务的工作队列,只接受被提交的Runnable接口类
  • threadFactory:线程工厂,专门生产新线程
  • handler:当任务执行被阻塞时,用它来处理,默认是“拒绝执行处理器”,其会抛出一个 RejectedExecutionException
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;
}

2. 实现 ExecutorService 接口的 submit()方法

ThreadPoolExecutor 没有重写 submit(),被调用的是其父类 AbstractExecutorService 实现的 submit(),查看 AbstractExecutorService

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    //将 Runnable 封装成一个 RunnableFuture,对于 Runnable 意义不大,其主要针对 Callable 
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    //执行任务,由子类 ThreadPoolExecutor 实现
    execute(ftask);
    //返回 Future 接口,可返回最终计算结果,对于 Runnable 意义不大,其主要针对 Callable 
    return ftask;
}

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

查看 ThreadPoolExecutor 的 execute(Runnable command) 方法

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();

    //获取线程池状态值,其包含两个核心属性(方便同时对两个值的原子操作,底层采用了 CAS 而非锁)
    //1.workerCount,有效线程数(代表那些已启动但不准停止的线程数量,与实际线程数可能不符)
    //2.runState,主要用于线程池生命周期的控制
    int c = ctl.get();

    //如果有效线程数少于corePoolSize,创建一个Worker(包含一个新的核心线程)
    if (workerCountOf(c) < corePoolSize) {
        //如果创建成功,将command作为首次任务,因此不需要任务入队,可立即返回
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //如果线程池可接收新的任务,尝试将任务入队
    if (isRunning(c) && workQueue.offer(command)) {
        //任务入队成功,必须进行二次检查
        int recheck = ctl.get();
        //检查:如果线程池已停止接收,回滚已入队的任务并拒绝
        if (! isRunning(recheck) && remove(command))
            reject(command);
        //如果有效线程数为0,创建一个Worker(包含一个新的额外线程),其不存在首次任务,故只能从工作队列中依次取任务
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
        //当然,如果有效线程数不为0,不用管它,等待现有的空闲线程从工作队列中依次取任务即可
    }
    //(为了缓冲任务过多、队列已满)尝试创建一个Worker(包含一个新的额外线程),将command作为首次任务
    else if (!addWorker(command, false))
        //一旦创建失败了,意味着线程池已停工或饱和,直接拒绝
        reject(command);
}

可以看到,核心的几个调用分别是① addWorker(command, true) 创建一个核心线程(一般不会被销毁),首次执行command,后正常运行;② addWorker(null, false) 创建一个额外线程,从队列中依次取任务;③ addWorker(command, false) 创建一个额外线程,首次执行command,后正常运行

查看源码 ThreadPoolExecutor 的 addWorker(Runnable firstTask, boolean core)

private boolean addWorker(Runnable firstTask, boolean core) {
    //在环境允许时,将有效线程数+1(使用CAS原语保证同步,性能高于锁)
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        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
        }
    }

    //一旦线程数成功+1,开始创建新线程

    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;
            //使用锁同步,将新线程加入池中(池的类型是HashSet,本身是非线程安全的)
            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 {
        //如果新线程产生各种失败,回滚整个流程:从池中删除它、线程数-1、尝试终止线程池
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}

工作线程所运行的非常核心的run()由Worker类来实现,查看ThreadPoolExecutor.Worker源码

//Worker构造函数
Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    //使用工厂类来新建一个工作线程
    this.thread = getThreadFactory().newThread(this);
}

//传递给工作线程的run()方法
public void run() {
    runWorker(this);
}

final void runWorker(Worker w) {
    //注意,当前线程为工作线程,而非主线程
    Thread wt = Thread.currentThread();
    //设置首次任务
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        //获得首次任务,或从工作队列中获取最旧的任务(FIFO队列)
        //由于是阻塞式的生产者/消费者队列,当缺少任务时,当前线程等待并挂起
        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 {
                    //执行任务(队列只接受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();
            }
        }
        //当线程数超过了最大值、或线程池停止、或线程超时,则getTask()返回null,代码到达此处
        completedAbruptly = false;
    } finally {
        //根据运行异常或线程池配置问题(例如最大数量、超时),选择性地进行线程销毁处理
        processWorkerExit(w, completedAbruptly);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值