线程池源码分析---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执行任务(主要包括:如果成功的话和第一步逻辑一样,区别在于这里判断的是线程数是否大于等于最大线程数),失败执行拒绝策略。
相关推荐
bobz96521 分钟前
IKEv1 和 IKEv2 发展历史和演进背景
后端
大鹏dapeng34 分钟前
Gone v2 goner/gin——试试用依赖注入的方式打开gin-gonic/gin
后端·go
tan180°1 小时前
版本控制器Git(1)
c++·git·后端
GoGeekBaird1 小时前
69天探索操作系统-第50天:虚拟内存管理系统
后端·操作系统
_丿丨丨_1 小时前
Django下防御Race Condition
网络·后端·python·django
JohnYan2 小时前
工作笔记 - btop安装和使用
后端·操作系统
我愿山河人间2 小时前
Dockerfile 和 Docker Compose:容器化世界的两大神器
后端
掘金码甲哥2 小时前
golang倒腾一款简配的具有请求排队功能的并发受限服务器
后端
重庆穿山甲2 小时前
装饰器模式实战指南:动态增强Java对象的能力
后端
卑微小文2 小时前
企业级IP代理安全防护:数据泄露风险的5个关键防御点
前端·后端·算法