ThreadPoolExecutor源码分析

目录

ThreadPoolExecutor核心参数

ThreadPoolExecutor执行流程

ThreadPoolExecutor状态

 线程池状态转换

execute方法

addWorker方法 

 worker对象

runWorker方法 

getTask方法

processWorkerExit方法 


ThreadPoolExecutor核心参数

public ThreadPoolExecutor(int corePoolSize,   //核心线程数
                          int maximumPoolSize, //最大线程数
                          long keepAliveTime,  //非核心线程空闲时间
                          TimeUnit unit,       //keepAliveTime的单位
                          BlockingQueue<Runnable> workQueue, //工作队列
                          ThreadFactory threadFactory,  //线程工厂
                          RejectedExecutionHandler handler) //拒绝策略

ThreadPoolExecutor执行流程

ThreadPoolExecutor状态

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
Integer.SIZE=32 COUNT_BITS=29
ctl表示两个状态 
1表示线程池当前状态 高三位  
2表示当前线程池当前工作线程个数 低二十九位
private static final int COUNT_BITS = Integer.SIZE - 3;
表示最大工作线程数
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// 线程池的工作状态
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;
//计算当前线程池的状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//计算当前线程池的工作线程个数
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }

 线程池状态转换

execute方法

第一点核心  通过execute方法 查看到线程池的整个执行流程  以及避免并发情况判断

第二点核心  为什么添加一个空任务的非核心线程到线程池

注意该方法没有锁  所以在存在并发情况

    public void execute(Runnable command) {
	
	    //非空判断
        if (command == null)
            throw new NullPointerException();
       // 获取ctl属性
        int c = ctl.get();
		//工作线程个数是否小于核心线程数
        if (workerCountOf(c) < corePoolSize) {
		 //通过add方式 添加一个核心线程执行command任务
            if (addWorker(command, true))
			    //添加核心线程成功,返回true 直接return结束
                return;
			//如果是并发的情况下,添加核心线程失败的线程 需要重新获取一个ctl属性
            c = ctl.get();
        }
		//创建核心线程失败
		//判断当前线程池状态是否为running 
		//如果为running 执行offer方法将任务添加到任务队列中
        if (isRunning(c) && workQueue.offer(command)) {
		    //添加任务到工作队列中成功
			//再次获取ctl
            int recheck = ctl.get();
			//判断当前线程池状态是否为running,如果不是running状态,需要将任务从核心队列中请除
            if (! isRunning(recheck) && remove(command))
			    //执行拒绝 策略(线程池状态不对 执行拒绝策略)
                reject(command);
				//判断工作线程是否为 0
            else if (workerCountOf(recheck) == 0)
			    //工作线程为 0 但是工作队列中有任务在排队
				//添加一个空任务非核心线程 处理工作队列中排队的任务
                addWorker(null, false);
        }
		//添加工作队列失败 则添加非核心线程执行任务
        else if (!addWorker(command, false))
		    //添加非核心线程失败执行拒绝策略
            reject(command);
    }

addWorker方法 

添加工作线程 启动工作线程

   //添加工作线程
   private boolean addWorker(Runnable firstTask, boolean core) {
        //外层for循环的标识
        retry:
		//该for循环是对线程池状态的判断以及对工作线程数量的判断
        for (;;) { 
		    //获取到ctl
            int c = ctl.get();
			//拿到线程池的状态
            int rs = runStateOf(c);

            //如果线程池状态不为running 就在再次判断 查看当前任务是否可以不处理
            if (rs >= SHUTDOWN &&
			 //线程池状态为shutdown 并且任务为空   工作队列不为空  如果同时满足这三个条件那么就处理工作队列中的当前任务,该处是取反了
			! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty()))
			   //只要不是running状态 不处理新任务
			   //如果shutdown状态 并且满足了之前addWorker(null,false)并且任务队列中有任务 不走当前位置
                return false;

            for (;;) {
			    //基于ctl获取当前工作线程数量
                int wc = workerCountOf(c);
				   //判断工作线程是否大于最大值
                if (wc >= CAPACITY ||
				   //如果是核心线程 是否大于设置的corePoolSize 如果是非核心线程  是否大于maximumPoolSize 
                    wc >= (core ? corePoolSize : maximumPoolSize))
					//说明已经达到最大工作线程数了
                    return false;
				//以cas方式 对工作线程数 +1 如果成功 直接跳出外层for循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
				//重新获取ctl
                c = ctl.get();  // Re-read ctl
				// 基于重新获取的ctl拿到线程池的状态 判断和之前的rs状态是否一致 如果一致 走最里层for循环 重新获取工作线程数量
                if (runStateOf(c) != rs)
				    //说明并发操作导致线程池状态变化 需要重新判断状态 走最外层的for循环
                    continue retry;
               
            }
        }
        //添加工作线程,并启动工作线程
		//工作线程是否启动了
        boolean workerStarted = false;
		//工作线程是否添加了
        boolean workerAdded = false;
		//worker就是工作线程
        Worker w = null;
        try {
		    //new worker 构建工作线程 将任务扔到了worker中
            w = new Worker(firstTask);
			//拿到了worker中绑定的线程
            final Thread t = w.thread;
			//肯定不为null
            if (t != null) {
			   //加强    该锁避免了将线程池置为shutdown状态 
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
					 //基于重新获取的ctl 拿到线程池的状态
                    int rs = runStateOf(ctl.get());
                         //如果满足线程池状态为running 就添加工作线程
                    if (rs < SHUTDOWN ||
					    //如果线程池状态为shutdown 并且传入的任务为null
                        (rs == SHUTDOWN && firstTask == null)) {
						// 就开始添加工作线程
						//判断当前线程是否处于run状态  健壮性判断
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w); //将构建好的worker对象添加到workers中
                        int s = workers.size(); //获取工作线程个数
						//如果现在的工作线程数 大于历史最大的工作线程数 ,就重新赋值给largestPoolSize
                        if (s > largestPoolSize)
                            largestPoolSize = s;
						//将工作线程添加的标识设置为true
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                } 
				 
                if (workerAdded) {
				   //添加工作线程成功 启动线程
                    t.start();
					 //将工作线程启动的标识设置为true
                    workerStarted = true;
                }
            }
        } finally {
		        //启动工作线程失败
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;  //最终的返回状态就是worker是否启动
    }
	
	启动工作线程失败后 做的补救操作
	private void addWorkerFailed(Worker w) {
	//加锁
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
		    //判断当前创建工作线程是否成功
            if (w != null)
			    //如果成功 就将workers中的当前工作线程移除
                workers.remove(w);
			//将工作线程数 -1
            decrementWorkerCount();
			//尝试将线程池状态变成TIDYING
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

 worker对象

    private final class Worker
        extends AbstractQueuedSynchronizer //关于线程中断
        implements Runnable  //存储要执行的任务
    {
       
        private static final long serialVersionUID = 6138294804551838833L;

       // 工作线程的Thread对象 初始化时候构建出来的
        final Thread thread;
        //需要执行的任务 来源有两个  addworker方法 一个是从工作队列中获取的
        Runnable firstTask;
        
        volatile long completedTasks;

       
        Worker(Runnable firstTask) {
		   //刚刚初始化的工作线程不允许被中断的
            setState(-1); // inhibit interrupts until runWorker
			//第一个new的时候 会将任务赋值给firstTask
            this.firstTask = firstTask;
			//给worker构建Thread对象
            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方法 

执行任务的流程 并做了中断的判断

  //执行任务
  final void runWorker(Worker w) {
  //拿到当前工作线程
        Thread wt = Thread.currentThread();
		//拿到worker对象中封装的任务
        Runnable task = w.firstTask;
		//
        w.firstTask = null;
		//将worker的state归为0 代表可以被中断
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try { 
		    //获取任务的第一个方式 就是执行execute  submit时 传入的任务直接处理
			//获取任务的第二个方式 就是从工作队列中获取任务
            while (task != null || (task = getTask()) != null) {
			    //加锁 在shutdown状态下 当前线程不允许被中断
				// 并且worker内部实现的锁 并不是可重入锁 因为中断时 也需要对worker进行lock 不能获取就代表
				//当前工作线程正在执行任务
                w.lock();
                //如果线程池状态为stop状态  必须将当前线程中断 
				//第一个判断 判断当前线程池状态是否stop
				//第二个判断  查看中断标记位 并归位 如果为false 说明不是stop 
				//如果为true 需要再次判断是否为并发操作导致线程池为stop
                if ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() &&runStateAtLeast(ctl.get(), STOP))) 
				 //查询当前线程中断标记是否为false 如果为false 就执行wt.interrupt()
				&&!wt.isInterrupted())
				    //将中断标记设置为true
                    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
                    task = null;
					//执行成功的任务个数+1
                    w.completedTasks++;
					//将state标记位置为 0
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

getTask方法

如果从工作队列中获取任务

   private Runnable getTask() {
       //标识 (非核心线程可以干掉)
        boolean timedOut = false; // Did the last poll() time out?
        //死循环
		//=============================判断线程池状态==========================================
        for (;;) {
		    //获取ctl标识
            int c = ctl.get();
			//拿到线程池的状态
            int rs = runStateOf(c);
             //如果进入if 需要干掉当前工作线程
			 //线程池状态为shutdown stop
			 //如果线程池状态大于等于stop 需要移除当前工作线程
			 //如果线程池状态为shutdown 并且工作队列为null 需要移除当前工作线程
            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }
            
		 //=============================判断线程工作数量=============================
            int wc = workerCountOf(c); //拿到工作线程数

            // allowCoreThreadTimeOut 是否允许核心线程超时 一般都为false
			//工作线程是否大于核心线程
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
             //工作线程是否已经大于最大线程数了
			 //工作线程数大于核心线程数  并且当前线程已经超时
			 //尝试干掉当前线程
            if ((wc > maximumPoolSize || (timed && timedOut))
			    //工作线程数大于1 或者工作队列为空
				// 如果工作队列为空 我就干掉我自己
				// 如果工作线程数大于1 我就干掉我自己
                && (wc > 1 || workQueue.isEmpty())) {
				 //基于cas的方式移除掉当前线程 只有一个线程会cas成功
                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;
            }
        }
    }

processWorkerExit方法 

   //移除当前工作线程
   private void processWorkerExit(Worker w, boolean completedAbruptly) {
   
        //如果执行processWorkerExit方法的操作不是getTask中的操作 是直接因为钩子函数抛出异常
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
		    //因为执行方式不合法 手动扣减工作线程数
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
		    //记录当前线程池一共处理了多少个任务
            completedTaskCount += w.completedTasks;
			//移除工作线程
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }
        //尝试将 线程池关系 到过度状态
        tryTerminate();

        int c = ctl.get();
		//当前线程池状态  进到这里 说明是running 或shutdown
        if (runStateLessThan(c, STOP)) {
		    //如果是正常状态移除当前工作线程
            if (!completedAbruptly) {
			   //核心线程数最小值 允许多少
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
				//如果工作队列中的任务不为空 设置工作线程的最小值为1
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
					//还有工作线程在线程池中
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
			//说明不正常的方式移除当前工作线程  再添加一个工作线程
			//线程池工作队列不为空 并且没有工作线程 再次添加一个工作线程
            addWorker(null, false);
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值