线程池源码分析---ThreadPoolExecutor

ThreadPoolExecutor

重要属性字段

java 复制代码
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
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;
  • ctl是一个原子整数类,包含了2个概念:线程的有效数量(workerCount);运行状态(runState 运行、关闭等)。一个32bit位的int类型是如何包含这2个概念的呢?答案就是把32位拆成2部分,高3位标识runState,低29位标识线程数量。
  • COUNT_BITS 值是29
  • CAPACITY 容量(1<<29)-1 //00011111_11111111_11111111_11111111
  • RUNNING 左移29位 -1 << COUNT_BITS //11100000_00000000_00000000_00000000 表示接受新任务并处理排队的任务
  • SHUTDOWN 左移29位 0 << COUNT_BITS // 0b00000000_00000000_00000000_00000000 表示不接受新任务,但处理排队的任务
  • STOP 左移29位 1 << COUNT_BITS // 0b00100000_00000000_00000000_00000000 表示不接受新任务,不处理排队的任务,并中断正在进行的任务
  • TIDYING 左移2位 2 << COUNT_BITS // 0b01000000_00000000_00000000_00000000 表示所有任务都已终止,workerCount 为零,转换到状态的线程将运行 terminated()
  • TERMINATED 左移三位 3 << COUNT_BITS// 0b01100000_00000000_00000000_00000000 terminated()
  • 状态转换:RUNNING -> SHUTDOWN 在调用 shutdown() 时,可能隐式在 finalize() 中;(RUNNING or SHUTDOWN) -> STOP 调用 shutdownNow() 时;SHUTDOWN -> TIDYING 当 queue 和 pool 都为空时; STOP -> TIDYING 当 pool 为空时;TIDYING -> TERMINATED当 terminated()钩子方法完成时

主要构造函数

arduino 复制代码
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
  
}
  • corePoolSize 核心线程数。要保留在池中的线程数,即使它们处于空闲状态,除非设置了code allowCoreThreadTimeOut
  • maximumPoolSize 最大线程数。池中允许的最大线程数
  • keepAliveTime 存活时间。当线程数大于核心线程数时,这是多余的空闲线程在终止之前等待新任务的最长时间。
  • unit 时间单位。keepAliveTime参数的时间单位
  • workQueue 工作队列。用于在执行任务之前保留任务的队列。execute()方法提交的Runnable任务
  • threadFactory 线程工厂。生产线程的工厂
  • handler 拒绝策略。队列容量不够,工作线程大于等于最大线程数

Worker 对象

  1. 继承了同步器实现了Runnable
java 复制代码
private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable

继承AbstractQueuedSynchronizer实现锁的机制,确保任务执行期间不被别的线程干扰。

2.属性字段

  • final Thread thread;执行任务的线程
  • Runnable firstTask;初始任务
  • volatile long completedTasks;记录该worker完成的任务数
  1. 构造方法
scss 复制代码
Worker(Runnable firstTask) {
    //状态设置为-1 
    //interruptIfStarted()方法的时候会判断>=0才会中断
    setState(-1); // inhibit interrupts until runWorker
    //任务
    this.firstTask = firstTask;
    //线程池构建的worker
    this.thread = getThreadFactory().newThread(this);
}
  1. 方法

isHeldExclusively()

typescript 复制代码
protected boolean isHeldExclusively() {
    return getState() != 0;
}

判断当前线程是否持有锁,0 表示解锁状态, 1 表示持有锁

tryAcquire(int unused)

加锁方法

arduino 复制代码
protected boolean tryAcquire(int unused) {
  //CAS设置锁的状态为1
   if (compareAndSetState(0, 1)) {
       setExclusiveOwnerThread(Thread.currentThread());
       return true;
   }
   return false;
}

tryRelease(int unused)

解锁方法

java 复制代码
protected boolean tryRelease(int unused) {
    setExclusiveOwnerThread(null);
    //设置为0,释放锁
    setState(0);
    return true;
}

interruptIfStarted()

中断线程

scss 复制代码
void interruptIfStarted() {
    Thread t;
    if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
        try {
            t.interrupt();
        } catch (SecurityException ignore) {
        }
    }
}

runWorker(this)

执行任务

csharp 复制代码
public void run() {
    //由worker构造方法 this.thread = getThreadFactory().newThread(this); 构建的线程启动后调用
    runWorker(this);
}
java 复制代码
final void runWorker(Worker w) {
    //获取当前线程
    Thread wt = Thread.currentThread();
    //获取初始任务
    Runnable task = w.firstTask;
    //清空初始任务
    w.firstTask = null;
    //释放锁将初始任务状态-1改为0,允许中断
    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
            
            
            //runStateAtLeast(ctl.get(), STOP) 线程池是STOP TIDYING TERMINATED等状态
            //Thread.interrupted() 当前线程中断成功
            // 并且 runStateAtLeast(ctl.get(), STOP))) 线程池是STOP TIDYING TERMINATED等状态
            //并且  !wt.isInterrupted() 没有中断成功 再执行wt.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.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;
                //worker 执行的任务计数
                w.completedTasks++;
                //释放锁  执行完之后释放锁,这时候这个worker就可以继续执行任务了
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}
java 复制代码
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.
        //不是正常状态(RUNNING)或队列是空的
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
             //减小线程数
            decrementWorkerCount();
            return null;
        }
        //工作线程数量
        int wc = workerCountOf(c);

        // Are workers subject to culling?
        //是否容许核心线程超市或者工作线程数大于核心线程数
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        //判断是否需要减少线程数(线程数超过最大值或超时且无任务)
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            //CAS 线程数减一
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            //从队列获取任务
            Runnable r = timed ?
            //允许核心线程超时或者线程池数大于核心线程数 keepAliveTime时间内获取任务
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                //获取任务 没任务时等待任务
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}
scss 复制代码
private void processWorkerExit(Worker w, boolean completedAbruptly) {
    //因一场退出,减少线程数
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    //获取锁 因为不只是一个worker线程 防止互相干扰
    mainLock.lock();
    try {
        //累加线程池worker完成的任务数
        completedTaskCount += w.completedTasks;
        //移除工作线程  
        workers.remove(w);
    } finally {
        //释放锁 给别的worker执行
        mainLock.unlock();
    }
    //尝试终止线程池 
    tryTerminate();

    int c = ctl.get();
    //线程池状态为RUNNING或SHUTDOWN
    if (runStateLessThan(c, STOP)) {
        //正常退出
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            // 允许核心线程超时且队列不为空 退出  
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            //至少还有一个工作线程  
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        //至少要有一个工作线程
        addWorker(null, false);
    }
}
scss 复制代码
final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        //检查是否允许终止
        if (
        //运行状态
        isRunning(c) ||
            //TIDYING或TERMINATED
            runStateAtLeast(c, TIDYING) ||
            //SHUTDOWN状态,队列不为空
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
            //工作线程不为0
        if (workerCountOf(c) != 0) { // Eligible to terminate
             //终端一个worker
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //CAS设置状态为TIDYING
            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
    }
}

任务提交分析(execute()方法)

scss 复制代码
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    //工作线程数小于核心线程数,创建一个worker去执行任务
    if (workerCountOf(c) < corePoolSize) {
        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);
    }
    //添加一个worker执行任务
    else if (!addWorker(command, false))
        //失败执行拒绝策略
        reject(command);
}

addWorker()

  1. int c = ctl.get()获原子类的值默认ctlOf(RUNNING, 0),workerCountOf(c) < corePoolSize工作线程小于核心线程数。

ctlOf(RUNNING, 0)

arduino 复制代码
private static int ctlOf(int rs, int wc) { return rs | wc; }

rs是RUNNING入参二进制是11100000_00000000_00000000_00000000,wc入参是0, rs|wc 就是高三位的状态值 workerCountOf(c)

arduino 复制代码
private static int workerCountOf(int c)  { return c & CAPACITY; }

workerCountOf(c)方法的计算c & CAPACITY(c & 00011111_11111111_11111111_11111111),屏蔽掉高三位拿到低29位得到工作线程数

  1. addWorker(command, true)
java 复制代码
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
       
        int c = ctl.get();
        // c & ~CAPACITY  获取状态值(高三位)
        //~CAPACITY 先取反拿到高三位,再c&取反的值,获取状态值
        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;
                //CAS操作把工作线程数加一
                //成功了结束双层循环
            if (compareAndIncrementWorkerCount(c))
                break retry;
                //重新获取状态 因为这时候线程池可能不是处于RUNNING状态
            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 {
        //构造worker
        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;
}

拒绝策略

1. 默认拒绝策略介绍

RejectedExecutionHandler 默认有4个实现

  • AbortPolicy 抛异常
typescript 复制代码
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    throw new RejectedExecutionException("Task " + r.toString() +
                                         " rejected from " +
                                         e.toString());
}
  • CallerRunsPolicy 线程池不是关闭状态,由调用任务的线程自己执行
scss 复制代码
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        r.run();
    }
}
  • DiscardOldestPolicy 丢弃最早的任务并继续由线程池执行
scss 复制代码
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        //从队列头部删除一个任务,也就是最早的任务
        e.getQueue().poll();
        e.execute(r);
    }
}
  • DiscardPolicy 丢弃任务
typescript 复制代码
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    //啥都不做
}
java 复制代码
private static final RejectedExecutionHandler defaultHandler =
    new AbortPolicy();

2. 拒绝策略扩展

默认提供的拒绝策略是抛异常

java 复制代码
private static final RejectedExecutionHandler defaultHandler =
    new AbortPolicy();

自定义拒绝策略是实现RejectedExecutionHandler 接口,在构建线程池的时候通过构造方法传参指定即可

线程池执行流程总结

  1. 工作线程数小于核心线程数,添加一个worker执行任务(这其中核心包括:若是第一任务直接执行,接下来循环从任务队列中拿任务去执行,直到任务队列空了);
  2. 否则添加到任务队列;
  3. 否则添加一个worker执行任务(主要包括:如果成功的话和第一步逻辑一样,区别在于这里判断的是线程数是否大于等于最大线程数),失败执行拒绝策略。
相关推荐
爱勇宝9 分钟前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
AskHarries26 分钟前
工具失败时怎么办:重试、回滚、人工确认和风险提示
后端·程序员
苏三说技术2 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎3 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode3 小时前
Redis 在生产项目的使用
前端·后端
用户559822481223 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode3 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战3 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha3 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn3 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端