线程池02--源码

上一篇:https://blog.csdn.net/fengxianaa/article/details/124448911

想要理解源码,看是不行的,必须 debug跟进去

1. 主要变量

ThreadPoolExecutor 类中的属性

//用来标记线程池状态(高3位),线程个数(低29位)
//默认是RUNNING状态,线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

//线程掩码位数,int类型是32位,所以值为29
private static final int COUNT_BITS = Integer.SIZE - 3;

//线程最大个数(低29位)00011111111111111111111111111111
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

//线程池状态
//(高3位):111 00000000000000000000000000000  接受新任务并且处理阻塞队列里的任务
private static final int RUNNING    = -1 << COUNT_BITS;

//(高3位):000 00000000000000000000000000000  拒绝新任务但是处理阻塞队列里的任务
private static final int SHUTDOWN   =  0 << COUNT_BITS;

//(高3位):001 00000000000000000000000000000  拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务的线程
private static final int STOP       =  1 << COUNT_BITS;

//(高3位):010 00000000000000000000000000000  所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为 0,将要调用 terminated 方法
private static final int TIDYING    =  2 << COUNT_BITS;

//(高3位):011 00000000000000000000000000000  终止状态,terminated方法调用完成以后的状态
private static final int TERMINATED =  3 << COUNT_BITS;
// 获取高三位 线程池状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }

//获取低29位 线程个数
private static int workerCountOf(int c)  { return c & CAPACITY; }

//计算ctl新值,线程状态 与 线程个数
private static int ctlOf(int rs, int wc) { return rs | wc; }


1.RUNNING -> SHUTDOWN:显式调用 shutdown() 方法,或者隐式调用了 finalize(),它里面调用了 shutdown() 方法。
2.RUNNING or SHUTDOWN -> STOP:显式调用 shutdownNow() 方法时候。
3.SHUTDOWN -> TIDYING:当线程池和任务队列都为空的时候。
4.STOP -> TIDYING:当线程池为空的时候。
5.TIDYING -> TERMINATED:当 terminated() hook 方法执行完成时候。

2. execute方法

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
    	//获取当前线程池的状态+线程个数变量的组合值
        int c = ctl.get();
    	/**
 		 * 1. 如果 线程数<corePoolSize,新建线程运行
         *    如果,新建线程失败,则继续下一步
         */
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))// 
                return;
            c = ctl.get();
        }
    	/**
 		 * 2. 如果 线程池是RUNNING 把任务放到等待队列中
         */
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 再次校验,如果 线程池状态不是RUNNING,则从队列删除任务,并执行拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // 如果当前线程池线程空,则添加一个线程
            else if (workerCountOf(recheck) == 0)
                // 第一个参数为空,表示该线程需要从队列中获取任务
                addWorker(null, false);
        }
    	//3. 如果队列满了,则新增线程,新增失败则执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

3. addWorker方法

private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();//获取当前线程池的状态+线程个数变量的组合值
            int rs = runStateOf(c);//获取线程池状态

            //如果 线程池状态>SHUTDOWN,不新增线程
            //如果 线程池状态=SHUTDOWN 且 firstTask不是null,不新增线程
            //如果 线程池状态=SHUTDOWN 且 firstTask是null 但 workQueue是空的,不新增线程
            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;
                c = ctl.get();  
                // 如果cas失败,则看线程池状态是否变化了,
                //     是:则跳到外层循环重试重新获取线程池状态,
                //     否:内层循环重新cas。
                if (runStateOf(c) != rs)
                    continue retry;
            }
        }
		//到这里说明cas成功
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;//worker实现了Runnable接口
        try {
            //创建线程
            w = new Worker(firstTask);
            /**
            Worker(Runnable firstTask) {
                setState(-1); // 在执行runWorker前,禁止中断该线程,shutdownNow中会判断该状态,如果>=0才中断
                this.firstTask = firstTask;
                this.thread = getThreadFactory().newThread(this);
        	}
             */
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    //获取状态
                    int rs = runStateOf(ctl.get());
					// 如果线程池是运行状态 或 (SHUTDOWN状态 && firstTask是null)
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive())
                            throw new IllegalThreadStateException();
                        workers.add(w);//把新建的线程放到集合中
                        int s = workers.size();
                        // largestPoolSize 记录线程池运行时候一共创建了几个线程
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;//表示线程新增成功
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

4. runWorker方法

addWorker 方法中的 t.start(),这句代码执行后,会进入 Worker 类的 run 方法,最终进入 runWorker 方法

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    //将state设置为0,允许中断该线程
    w.unlock();
    boolean completedAbruptly = true;
    try {
        //如果任务不为null,或者从任务队列中获取的任务不为null,则执行while循环
        while (task != null || (task = getTask()) != null) {
            //如果任务不为空,则获取Worker工作线程的独占锁,避免执行任务时其他线程操作这个Worker
            w.lock();
            //如果 状态>=STOP && 线程没有被中断,那么中断该线程
            //如果 线程已中断(interrupted方法会清除中断标记) && 状态>=STOP && 线程没中断,那么中断该线程
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                //中断线程,这里注意,如果这句代码执行
                //我们提交的任务对象的run方法中,如果有阻塞,会报InterruptedException
                wt.interrupt();
            try {
                //执行任务前执行的逻辑
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    //调用任务对象的run方法执行任务
                    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;
                //完成的任务数量加1
                w.completedTasks++;
                //释放工作线程获得的锁
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        //执行退出Worker线程的逻辑
        processWorkerExit(w, completedAbruptly);
    }

5. getTask方法

//获取一个Task执行,或阻塞,或有超时限制的等待。返回空,则当前线程结束
private Runnable getTask() {
        boolean timedOut = false; // 从队列中拿到空的任务时,设置为true,是允许当前线程结束的条件之一

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            //当线程池状态是SHUTDOWN且队列为空,或 状态>SHUTDOWN,返回null,即线程池结束
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);//当前线程池数量

            //允许当前线程结束的条件之一
            //allowCoreThreadTimeOut:是否允许核心线程超时,默认false,可以通过allowCoreThreadTimeOut方法修改
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
			
            //线程数>maximumPoolSize时,返回null,当前线程可以结束
            //当线程数>corePoolSize 且 当前线程没有从队列中拿到任务 且 队列为空时,当前线程可以结束
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                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;//获取不到任务,设置为true
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

总结:当 getTask方法 返回 null 的时候,当前线程结束,有以下几种

  • 线程池状态是SHUTDOWN且队列为空
  • 线程状态>SHUTDOWN
  • 线程数>corePoolSize 且 当前线程没有从队列中拿到任务 且 队列为空
  • 线程数>maximumPoolSize时
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值