Java线程池源码

198 阅读7分钟

线程状态

图片.png

线程池中状态说明

1、RUNNING

(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(02) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
  • 1

2、 SHUTDOWN

(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。

3、STOP

(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。

4、TIDYING

(1) 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

5、 TERMINATED

(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

线程池源码状态

图片.png

ctl

内部有重要的成员变量ctl,类型是AtomicInteger,低29位表示线程池中线程数,通过高3位表示线程池的运行状态
COUNT_BITS的值是29
1、RUNNING:-1 << COUNT_BITS,即高3位为111,该状态的线程池会接收新任务;
2、SHUTDOWN: 0 << COUNT_BITS,即高3位为000,该状态的线程池不会接收新任务;
3、STOP : 1 << COUNT_BITS,即高3位为001;
4、TIDYING : 2 << COUNT_BITS,即高3位为010, 所有的任务都已经终止;
5、TERMINATED: 3 << COUNT_BITS,即高3位为011, terminated()方法已经执行完成

ThreadPoolExecutor 初始化参数

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

defaultThreadFactory 默认工厂工具类

public static ThreadFactory defaultThreadFactory() {
    return new DefaultThreadFactory();
}

DefaultThreadFactory 工具类 创建核心线程

static class DefaultThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

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

   //  r 就是封装的worker对象 这个对象实现了runnable接口
   // 所以当线程启动的时候回执行worker对象重写的run方法
    public Thread newThread(Runnable r) {
        // 创建线程 
        Thread t = new Thread(group, r,
                              namePrefix + threadNumber.getAndIncrement(),
                              0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
            // 返回创建的线程 
        return t;
    }
}

execute 执行任务

public void execute(Runnable command) 
{
    if (command == null)
        throw new NullPointerException();
  
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {  
    //workerCountOf获取线程池的当前线程数;小于corePoolSize,执行addWorker创建新线程执行command任务
       if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // double check: c, recheck
    // 线程池处于RUNNING状态,把提交的任务成功放入阻塞队列中
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // recheck and if necessary 回滚到入队操作前,即倘若线程池shutdown状态,就remove(command)
        //如果线程池没有RUNNING,成功从阻塞队列中删除任务,执行reject方法处理任务
        if (! isRunning(recheck) && remove(command))
            reject(command);
        //线程池处于running状态,但是没有线程,则创建线程
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    // 往线程池中创建新的线程失败,则reject任务
    else if (!addWorker(command, false))
        reject(command);
}

讲解

为什么需要double check线程池的状态? 在多线程环境下,线程池的状态时刻在变化,而ctl.get()是非原子操作,很有可能刚获取了线程池状态后线程池状态就改变了。判断是否将command加入workque是线程池之前的状态。倘若没有double check,万一线程池处于非running状态(在多线程环境下很有可能发生),那么command永远不会执行。

addWorker(Runnable firstTask, boolean core) firstTask 任务 core =true

 // firstTask 可以为 null ,表示启动worker之后,worker自动到queue中获取,
 //如果不是 null ,则worker执行firstTaSK
    // core 采用的线程数限制,如果为true 采用核心线程数 限制; false,
    //采用 maximumPoolSize 线程数限制
    // 返回值总结:
    // true: 表示创建worker成功,且线程启动

    // false : 表示创建worker失败
    // 1.线程池状态rs > SHUTDOWN
    // 2. rs == SHUTDOWN 但是队列中已经没有任务了 
    //或者当前状态是 SHUTDOWN 且队列未空,但是 firstTask不为 null
    // 3.当前线程已经达到指定指标(corePoolSize 或者 maximumPoolSize)
    // 4.线程池ThreadFactory 创建的线程是 null
    private boolean addWorker(Runnable firstTask, boolean core) 
    {
        // 自旋   判断当前线程池状态是否允许创建线程的事情。
        retry:
        for (;;) {
            // 获取当前的 ctl 值
            int c = ctl.get();
            // 获取当前线程池运行状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            // 条件一 : rs >= SHUTDOWN true: 表示当前线程池状态不是Running
            // 条件二: ! (rs == SHUTDOWN && firstTask == null && !                       workQueue.isEmpty())
            // true : 当线程池状态, rs > SHUTDOWN 或者 rs == SHUTDOWN 但是队列中已经没有任务了,或者 rs == SHOTDOWN 且 firstTask不为空
            if (rs >= SHUTDOWN &&
                    ! (rs == SHUTDOWN &&
                            firstTask == null &&
                            ! workQueue.isEmpty()))
                return false;

            // 以上代码就是判断当前线程池状态是否允许添加线程

            // 内部自旋 ,获取创建线程令牌的过程
            for (;;) {
                // 获取当前线程池中线程数量
                int wc = workerCountOf(c);
                // 条件一: wc >= CAPACITY 永远不成立,
                //CAPACITY是一个5亿多的数据
                // 条件二:   wc >= (core ? corePoolSize : maximumPoolSize)
                // core == true  ,判断当前线程数量是否 >= corePoolSize,
                //会拿核心线程数量做限制
                // core == false  ,判断当前线程数量是否 >= corePoolSize,
                会拿最大线程数量做限制
                if (wc >= CAPACITY ||
                        wc >= (core ? corePoolSize : maximumPoolSize))
                    // 表明当前无法添加新的线程了。
                    return false;
          // true: 说明记录线程数量已经 +1成功了,相当于申请到了一块令牌。              
  // false : 说明其他线程修改过了ctl 值了。可能其他线程execute() 申请过令牌了。
                if (compareAndIncrementWorkerCount(c))
                    // cas 成功,申请到令牌了
                    // 直接跳出了 retry 外部的自旋
                    break retry;

                // 没申请到令牌,再次获取ctl的最新值
                c = ctl.get();  // Re-read ctl
                // 判断当前线程池状态是否发生过改变,
                //如果外部在这之前调//shutDown, shutDown会导致状态发生改变
                if (runStateOf(c) != rs)
                    // 状态发生改变后,返回到外层循环
                    continue retry;
            }
        }
        // 来到了这里
        // 表示创建的worker是否已经启动, false 未启动
        boolean workerStarted = false;
        // 创建的 worker是否添加到池子中,默认false, 未添加
        boolean workerAdded = false;
        // 表示 后面创建worker的一个引用
        Worker w = null;
        try 
        {
            // 创建worker,执行完后,线程创建完毕
            w = new Worker(firstTask);
            // 将创建的线程节点, 赋值
            final Thread t = w.thread;
            // 进行了一次判断,为什么要判断?
            if (t != null) 
            {
                // 将全局锁的引用保存到  mainLock
                final ReentrantLock mainLock = this.mainLock;
                // 持有全局锁,可能会阻塞,知道获取成功为止,
                //同一时刻,操作线程池内部相关的操作,都必须持有锁
                mainLock.lock();
                try 
                {
                   
                    // 再次去获取最新的ctl 值,即运行状态
                    int rs = runStateOf(ctl.get());

                    // 条件一: true: 表示 当前线程池为正常的RUNNING状态
                    // 条件二: (rs == SHUTDOWN && firstTask == null)
                    // true: 当前的线程状态为  SHUTDOWN ,且  firstTask 为空
                    if (rs < SHUTDOWN ||
                            (rs == SHUTDOWN && firstTask == null)) {

                        // 当线程start后,线程isAlive会返回true ;
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
// 添加到线程池中 就是把创建的线程对象保存到hashSet集合中
                        workers.add(w);
                        // 获取最新的 线程池中的worker的数量
                        int s = workers.size();
                        // true :说明当前线程数量时一个新高了,更新最大值
                        if (s > largestPoolSize)
                            //其实这个值就是记录当前线程池中线程的数量
                            // 一个worker 对象代表一个线程
                            largestPoolSize = s;

                        // 表示线程已经加入到线程池中了
                        workerAdded = true;
                    }
                } finally {
                    // 解锁
                    mainLock.unlock();
                }

                // 说明当前添加worker添加是成功的
                if (workerAdded) {
                    // 启动线程
                    // 这里很关键 启动创建的线程 这样的话会执行
                    // 线程中的run 方法
                    t.start();
                    // 启动标记设置为true
                    workerStarted = true;
                }
            }
        } finally {
            // 如果整个条件成立,说明启动失败,需要做清理工作
            if (! workerStarted)
                // 1.释放令牌
                // 2.当前worker 清理出workers 集合
                addWorkerFailed(w);
        }

        // 返回新创建的线程是否启动
        return workerStarted;
    }

Worker 对象封装了创建的线程对象thread

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;

    // 创建的线程
    final Thread thread;
    //线程要执行的匿名内部类runnable接口 execute方法传入的参数
    Runnable firstTask;
    
    volatile long completedTasks;

    
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        // 线程要执行的匿名内部类runnable接口
        this.firstTask = firstTask;
        // this 就是创建的worker 对象 这段源码在上面
        this.thread = getThreadFactory().newThread(this);
    }

    /** Delegates main run loop to outer runWorker  */
    public void run() 
    {
        // 当线程执行start方法的时候 真正执行的是这个方法
        runWorker(this);
    }

    // Lock methods
    //
    // The value 0 represents the unlocked state.
    // The value 1 represents the locked state.

    protected boolean isHeldExclusively() {
        return getState() != 0;
    }

    protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }

    public void lock()        { acquire(1); }
    public boolean tryLock()  { return tryAcquire(1); }
    public void unlock()      { release(1); }
    public boolean isLocked() { return isHeldExclusively(); }

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

runWorker 线程真正执行的方法 封装在run 方法中

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try 
    {
        // 创建的线程为啥不会自己死掉 原因就在getTask方法是阻塞的
        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.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);
    }
}

getTask 获取队列中要执行的任务

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.
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }
        // 跑到这里说明线程池还处于RUNNING状态,重新获取一次工作线程数
        int wc = workerCountOf(c);

        // Are workers subject to culling?
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

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

非核心线程回收逻辑

核心就是上面的代码,其中allowCoreThreadTimeOut默认为false的,wc表示当前线程池中的线程数量,如果数量大于核心线程数,则执行带超时的poll方法,这样一段时间没有任务的话会返回null,然后等待执行的线程就会执行完毕,进而销毁,否则会执行take方法,该方法会一直阻塞,这也就是为什么核心线程会不断存在的原因。

其实并没有核心线程和非核心线程的区分,只是通过数量来判断是否该回收线程,回收的线程就被成为非核心线程,可以设置allowCoreThreadTimeOut为true,这样每个线程在固定的时间内拿不到任务就会被回收。

当超时后,则拿到的任务就是个null,执行销毁逻辑,从hashset中将该work对象移除,