线程池原理剖析二

线程池原理剖析二

系列回顾

在上一篇只说了线程池的基本策略和一个案例,可以参考看看线程池原理剖析一

ThreadPoolExecutor

部分注释翻译

	ctl是线程池的一个控制状态量(AtomicInteger),他打包了两个变量,一个是workerCount,另一个runState
	1:The main pool control state, ctl, is an atomic integer packing two conceptual fields
       1.1:workerCount, indicating the effective number of threads 工作线程数量
       1.2:runState,    indicating whether running, shutting down etc 线程池运行状态
         
      为了把他们两打包成一个int,我们限制workerCount最大值为2^29-1
     2:In order to pack them into one int, we limit workerCount to (2^29)-1 
     
       运行状态提供了几个生命周期控制的值如下  
     3:The runState provides the main lifecycle control, taking on values:
           3.1:RUNNING:  Accept new tasks and process queued tasks 允许接收新任务,处理队列中的任务
          
           3.2:SHUTDOWN: Don't accept new tasks, but process queued tasks 不接收新任务但可以处理队列中的任务
         
          3.3:STOP: Don't accept new tasks, don't process queued tasks 不接收新任务不处理队列中的任务
                      and interrupt in-progress tasks  中断正在进行的任务
          
          3.4: TIDYING:  All tasks have terminated, workerCount is zero,所有任务停止,workerCount =0
		        线程状态转到TIDYING 会回调terminated()方法
               the thread transitioning to state TIDYING will run the terminated() hook method. 
           
          3.5:TERMINATED: terminated() has completed   terminated()执行完成
         
      4:线程池状态的转换
          4.1 RUNNING -> SHUTDOWN
          	调用shutdown
             On invocation of shutdown(), perhaps implicitly in finalize()
             
          4.2 (RUNNING or SHUTDOWN) -> STOP
          	 调用shutdownNow
             On invocation of shutdownNow()
             
          4.3 SHUTDOWN -> TIDYING
          	队列和池子都是空的
             When both queue and pool are empty
             
          4.4 STOP -> TIDYING
          	池子是空的
             When pool is empty
             
          4.5 TIDYING -> TERMINATED
          	terminated执行完成
             When the terminated() hook method has completed

静态变量分析

	//包装runState和workerCount的AtomicInteger
	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
	//Integer.SIZE - 3 = 29,为什么是29? 因为有5个状态量,两位表示不了,只能三位表示。
    private static final int COUNT_BITS = Integer.SIZE - 3;
    //000111..1111 总共29个1
    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;

    // Packing and unpacking ctl
    //解包装成runState
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    //解包装成workerCount
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    //包装成ctl
    private static int ctlOf(int rs, int wc) { return rs | wc; }

先从5个状态量入手吧
RUNNING = -1 << COUNT_BITS; //-1左移29位
-1怎么表示?计算机是补码表示的,而负数的补码表示是正数源码取反+1
1:00…0001(31个0) 取反后111…110(31个1)
-1:11…111(32个1)
RUNNING = 11100…000(29个0)
SHUTDOWN = 00000…000(32个0)
STOP = 00100…000(29个0)
TIDYING = 01000…000(30个0)
TERMINATED = 01100…000(29个0)

高三位
RUNNING = 111
SHUTDOWN =000
STOP =001
TIDYING =010
TERMINATED =011

//解包装成workerCount
private static int workerCountOf(int c) { return c & CAPACITY; }
c=ctl.get()
00011…111(29个1) &c = 低29位 ,也就是workerCount

//解包装成runState
private static int runStateOf(int c) { return c & ~CAPACITY; }
11100…000(29个0)&c = 高三位 也就是runState

//包装成ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
runState|workerCount = 高三位|低29位 = 32位 = ctl

execute方法分析

   /**
     *  在未来某个时刻执行该任务,这个任务可能是新线程执行也可能是线程池已有的线程执行
     *  如果一个任务不可以提交执行,有下述几个原因:
     *     executor已经被shutdown
     *     容量到达阈值
     */
     //这个方法的执行策略和我[线程池原理剖析一]里面提到的提交策略是一样的
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        
        int c = ctl.get();
        //如果工作线程<corePoolSize 就开启新线程执行这个任务
        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);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //队列已满,尝试创建线程执行任务,失败后执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

addWorker方法分析

这个方法主要做两件事,其一是workCount++,其二是创建线程,线程包装的任务是Worker

	/**
 * 在当前线程池状态,给定的corePoolSize,maxPoolSize的限制下
 * 检查一个新线程是否可以被创建,如果可以创建,
 * 那么workerCount会相应改变并且会执行第一个任务
 * 这个方法返回false的情况如下:
 * pool is stopped
 * eligible to shut down
 * 线程工厂创建线程失败
 *
 * 如果线程工厂创建线程失败,可能是因为工厂返回null,也可能是异常
 * 典型异常就是在Thread.start()时内存溢出
 * 这种情况下我们要回滚做清理操作

 * @param core true:corePoolSize as bound , else maxPoolSize as bound
 * @return true if successful
 */
	private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);// 线程池状态

            // 这里有5种情况会返回false,(SHUTDOWN 不接收新任务但可以处理队列中的任务)
            //case1:rs = STOP
            //case2:rs = TIDYING
            //case3:rs = TERMINATED
            //case4:rs = SHUTDOWN && firstTask != null
            //case5:rs = SHUTDOWN && 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;
                if (compareAndIncrementWorkerCount(c))//cas尝试把workerCount加1
                    break retry;//跳出retry下面这个外层循环
                c = ctl.get();  // Re-read ctl //cas失败
                if (runStateOf(c) != rs)//如果线程池状态在这期间发生改变
                    continue retry;继续retry下面这个外层循环,去检查可不可以接受这个任务
                //如果线程池状态在这期间没有发生改变,继续内层循环cas操作
           
            }
        }
		//到这里了workerCount一定做了+1操作,但是线程还没有创建,下面就是创建线程 TODO
        boolean workerStarted = false; //工作/活跃线程 启动标志
        boolean workerAdded = false;//工作/活跃线程 添加到works(这是个set)标志
        Worker w = null;
        try {
            //Worker extends AQS implements Runnable。是一个不可重入独占锁,包装了线程和任务。
            w = new Worker(firstTask);
            final Thread t = w.thread;//worker包装的线程
            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());//线程池的状态
					//SHUTDOWN态不允许接受新任务,但可以执行阻塞队列里的任务
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {//运行态或者(SHUTDOWN 态 且 任务==null)
                       	//这个时候这个线程还没有启动,如果启动了,抛异常
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);//set集合把worker添加进去,这个集合存储的是工作/活跃线程
                        //阻塞队列存储的是超过corePoolSize的任务
                        int s = workers.size();
                        if (s > largestPoolSize)//更新largestPoolSize
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();//启动线程,回调Worker类里的run方法
                    workerStarted = true;
                }
            }
        } finally {
        	//如果进了if,可能是t==null||t.isAlive()||t.start()抛出oom
            if (! workerStarted)
                addWorkerFailed(w);//回滚处理
                //上面这个方法主要干三件事如下
             	//works.remove(w)
             	//workCount--
             	//尝试终止线程池tryTerminate
             	//Doug Lea 要求在可能会终止线程池的操作上必须执行tryTerminate方法,例如上面的remove(w)和workCount--
        }
        return workerStarted;
    }

runWorker方法

t.start会回调Worker类的run方法
public void run() {
runWorker(this);
}

	final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;//任务,可能为null
        w.firstTask = null;
        //Worker state初始为-1,调用tryRelease()方法,
        //将state置为0, interruptIfStarted()中只有state>=0才允许调用中断
        w.unlock(); // allow interrupts,
        boolean completedAbruptly = true;//
        try {
        	//只有task为null才会从阻塞队列中拿任务
            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();//回调我们自己的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);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值