java线程池源码分析


构造方法

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

corePoolSize–线程池长期维持的线程数
maximumPoolSize–最大线程数
keepAliveTime–线程空闲时间,超过这个时间会被回收
workQueue–任务阻塞队列
threadFactory–生产线程工厂,使用默认即可
handler–拒绝策略

线程池结构

//高三位表示线程池状态,低29位表示线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

//表示可接受新任务,且可执行队列中的任务;
private static final int RUNNING    = 111 00000 00000000 00000000 00000000;
//表示不接受新任务,但可执行队列中的任务;
private static final int SHUTDOWN   = 000 00000 00000000 00000000 00000000; 
//表示不接受新任务,且不再执行队列中的任务,且中断正在执行的任务
private static final int STOP       = 001 00000 00000000 00000000 00000000;
//所有任务已经中止,且工作线程数量为0,最后变迁到这个状态的线程将要执行terminated()钩子方法,只会有一个线程执行这个方法
private static final int TIDYING    = 010 00000 00000000 00000000 00000000;
//中止状态,已经执行完terminated()钩子方法
private static final int TERMINATED = 011 00000 00000000 00000000 00000000;

private static int ctlOf(int rs, int wc) { return rs | wc; }

//控制核心线程数量内的线程 是否可以被回收。true 可以,false不可以。
private volatile boolean allowCoreThreadTimeOut;
//拒绝策略
private volatile RejectedExecutionHandler handler;
//当allowCoreThreadTimeOut == false 时,会维护核心线程数量内的线程存活,超出部分会被超时,allowCoreThreadTimeOut == true 核心数量内的线程 空闲时 也会被回收
private volatile long keepAliveTime;
//任务队列,当线程池中的线程达到核心线程数量时,再提交任务 就会直接提交到 workQueue
private final BlockingQueue<Runnable> workQueue;
//线程池全局锁,增加worker 减少 worker 时需要持有mainLock , 修改线程池运行状态时,也需要。
private final ReentrantLock mainLock = new ReentrantLock();
//线程池中真正存放 worker->thread 的地方。
private final HashSet<Worker> workers = new HashSet<Worker>();

线程池状态

在这里插入图片描述
线程池状态不可逆,没有修改线程池状态的方法,除非shutdown、shutdownNow

任务提交

submit和execute都可以提交任务,submit用于提交关心返回结果的任务,execute用于提交不关心返回结果的任务。

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

public void execute(Runnable command){}

线程增加

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();
    }
    
/* 
执行到这里有两种情况
    1.当前线程池数量已经达到corePoolSize
    2.addWorker失败(要么线程池状态大于等于SHUTDOWN,要么刚好处于核心线程数-1,被其他线程抢先提交了)
    */
    
    //当前线程池处于running状态,尝试将task放入到workQueue中,这里使用offer不阻塞
    if (isRunning(c) && workQueue.offer(command)) {			
    	//双重检查,万一状态被其它线程修改了
        int recheck = ctl.get();
        //线程池非运行中,尝试把刚才添加的任务移除,如果移除成功说明还没被执行,直接拒绝。移除失败说明已经被其他线程执行了
        if (! isRunning(recheck) && remove(command))
            reject(command);
        //至少保证有1个线程去队列中取任务(corePoolSize=0可能出现这种情况)
        else if (workerCountOf(recheck) == 0)
        	//为null时,表示添加1个线程直接去任务队列取任务执行
            addWorker(null, false);
    }
    /*
    执行到这里,有两种情况
    1.offer失败。说明当前queue 满了,这个时候如果当前线程数量尚未达到maximumPoolSize的话,会创建新的worker直接执行command,假设当前线程数量达到maximumPoolSize的话,这里也会失败,走拒绝策略
    2.当前线程池是非running状态。这个时候因为command != null addWorker一定是返回false
    */
    else if (!addWorker(command, false))
        reject(command);
}

private boolean addWorker(Runnable firstTask, boolean core) {
   /**
      以下4种情况,添加失败:
	  1.线程池状态为STOP、TIDYING、TERMINATED,返回false
	  2.线程池状态等于SHUTDOWN且任务非空,返回false
	  3.线程池状态等于SHUTDOWN,任务为空且任务队列也为空,返回false,只有这个代码才可能出现
	    if (workerCountOf(recheck) == 0)
           //为null时,表示添加1个线程直接去任务队列取任务执行
           addWorker(null, false);
	  4.超过了线程数限制(core=true采用核心线程数限制,core=false采用maximumPoolSize线程数限制),返回false
   */
   retry:
   for (;;) {
       int c = ctl.get();
       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;
           if (compareAndIncrementWorkerCount(c))
               break retry;
           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 {
       w = new Worker(firstTask);
       final Thread t = w.thread;
       if (t != null) {
           final ReentrantLock mainLock = this.mainLock;
           //获取主锁,保护临界区。因为下面会添加worker到集合中
           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) {
           	   //启动worker,会执行worker的run方法
               t.start();
               workerStarted = true;
           }
       }
   } finally {
       if (! workerStarted)
           addWorkerFailed(w);
   }
   return workerStarted;
}

任务执行

Worker(Runnable firstTask) {
   setState(-1); // AQS状态为-1,不允许中断(线程都还没启动)
   this.firstTask = firstTask;
   this.thread = getThreadFactory().newThread(this);
}

public void run() {
   runWorker(this);
}

 final void runWorker(Worker w) {
     Thread wt = Thread.currentThread();
     //提交的第一个任务
     Runnable task = w.firstTask;
     w.firstTask = null;
     w.unlock(); // AQS的state为0,允许线程被中断了
     boolean completedAbruptly = true;
     try {
         //先执行提交的第1个任务,然后不断去队列中取任务
         while (task != null || (task = getTask()) != null) {		
         	 //Worker继续AQS,就是为了利用不可重入特性,这里加锁是避免万一被shutdown了,shutdown里也会去获取AQS锁,如果获取不到说明worker还在干活,获取到说明线程空闲就可以中断了。
             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
             /*
             1.线程池状态大于等于STOP,直接中断
             2.线程池状态小于STOP,清空线程的中断标志,不中断
             */
             if ((runStateAtLeast(ctl.get(), STOP) ||
                  (Thread.interrupted() &&
                   runStateAtLeast(ctl.get(), STOP))) &&
                 !wt.isInterrupted())
                 wt.interrupt();
             
             //使用try finally,即使钩子执行异常,异常也会被吞没。
             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);
     }
 }
private Runnable getTask() {
    // 是否超时
    boolean timedOut = false; // Did the last poll() time out?
    // 自旋
    for (; ; ) {
        int c = ctl.get();
        int rs = runStateOf(c);

        //当前程池状态是SHUTDOWN的时候会把队列中的任务执行完直到队列为空
        //线程池状态是STOP时,返回null,外层的runWorker会调用processWorkerExit来回收线程
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }
        // 获取工作线程数量
        int wc = workerCountOf(c);

        // 是否允许超时,有两种情况:
        // 1. 是允许核心线程数超时,这种就是说所有的线程都可能超时
        // 2. 是工作线程数大于了核心数量,这种肯定是允许超时的
        // 注意,非核心线程是一定允许超时的,这里的超时其实是指取任务超时
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
            //获取任务超时
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            // 真正取任务的地方
            // 默认情况,只有当工作线程数量大于核心线程数量时,才会调用poll方法触发超时调用,否则阻塞获取。poll(timeout, unit)方法会在超时时返回null
            Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

线程回收

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    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();
    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);
    }
}

线程池关闭

public void shutdown() {
   final ReentrantLock mainLock = this.mainLock;
   mainLock.lock();
   try {
       checkShutdownAccess();
       advanceRunState(SHUTDOWN);
       interruptIdleWorkers();
       onShutdown(); // hook for ScheduledThreadPoolExecutor
   } finally {
       mainLock.unlock();
   }
   tryTerminate();
}

public List<Runnable> shutdownNow() {
   List<Runnable> tasks;
   final ReentrantLock mainLock = this.mainLock;
   mainLock.lock();
   try {
       checkShutdownAccess();
       advanceRunState(STOP);
       interruptWorkers();
       tasks = drainQueue();
   } finally {
       mainLock.unlock();
   }
   tryTerminate();
   return tasks;
}

/**
 * Transitions to TERMINATED state if either (SHUTDOWN and pool
 * and queue empty) or (STOP and pool empty).  If otherwise
 * eligible to terminate but workerCount is nonzero, interrupts an
 * idle worker to ensure that shutdown signals propagate. This
 * method must be called following any action that might make
 * termination possible -- reducing worker count or removing tasks
 * from the queue during shutdown. The method is non-private to
 * allow access from ScheduledThreadPoolExecutor.
 */
final void tryTerminate() {
   for (;;) {
       int c = ctl.get();
       if (isRunning(c) ||
           runStateAtLeast(c, TIDYING) ||
           (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
           return;
       //1.shutdown且任务队列没有任务了
       //2.stop状态,尝试中断所有线程    
       if (workerCountOf(c) != 0) { // Eligible to terminate
           interruptIdleWorkers(ONLY_ONE);
           return;
       }

       final ReentrantLock mainLock = this.mainLock;
       mainLock.lock();
       try {
           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
   }
}

核心线程预热

/**
* Starts all core threads, causing them to idly wait for work. This
* overrides the default policy of starting core threads only when
* new tasks are executed.
*
* @return the number of threads started
*/
public int prestartAllCoreThreads() {
    int n = 0;
    //阻塞等待队列的任务
    while (addWorker(null, true))  
        ++n;
    return n;
}

/**
* Starts a core thread, causing it to idly wait for work. This
* overrides the default policy of starting core threads only when
* new tasks are executed. This method will return {@code false}
* if all core threads have already been started.
*
* @return {@code true} if a thread was started
*/
public boolean prestartCoreThread() {
   return workerCountOf(ctl.get()) < corePoolSize &&
       addWorker(null, true);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值