Java并发编程:ThreadPoolExecutor源码解析

1 介绍

线程池主要解决两个问题:一是当执行大量异步任务时线程池能够提供较好的性能。二是线程池提供了一种资源限制和管理的手段,比如可以限制线程的个数,动态增加线程数。

2 ThreadPoolExecutor类图

推荐ProcessOn在线画图软件,高清无码请点击
ThreadPoolExecutor类图
Integer类型用32位二进制表示,其中高三位表示线程池状态,后面29位用来记录线程池线程个数。

	// 默认是Running状态,线程个数为0	
	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
	// 线程个数掩码位数
    private static final int COUNT_BITS = Integer.SIZE - 3;
    // 线程的最大个数(低29位)00011111111111111111111111111111
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

	// 线程池状态 高三位存储
    // runState is stored in the high-order bits

	// 高三位 11100000000000000000000000000000
    private static final int RUNNING    = -1 << COUNT_BITS;
    // 高三位 00000000000000000000000000000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // 高三位 00100000000000000000000000000000
    private static final int STOP       =  1 << COUNT_BITS;
    // 高三位 01000000000000000000000000000000
    private static final int TIDYING    =  2 << COUNT_BITS;
    // 高三位 01100000000000000000000000000000
    private static final int TERMINATED =  3 << COUNT_BITS;

    // Packing and unpacking ctl
    // 获取高三位(运行状态)
    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; }

线程池状态:

  • RUNNING:接受新任务并且处理阻塞队列里的任务
  • SHUTDOWN:拒绝新任务但是处理阻塞队里的任务
  • STOP:拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务
  • TIDYING:所有任务都执行完(包含阻塞队列里的任务)后,当前线程池活动线程数为0时,将调用terminated方法
  • TERMINATED:终止状态。terminated方法调用完成以后的状态

线程池参数:

  • corePoolSize:线程池核心线程个数
  • workQueue:用于保存等待执行任务的阻塞队列,比如基于数组的有界ArrayBlockingQueue,基于链表的无界LinkedBlockingQueue,最多只有一个元素的同步队列SynchronousQueue以及优先级队列PriorityBlockingQueue等。
  • maximumPoolSize:线程池最大线程数量
  • ThreadFactory:创建线程的工厂
  • RejectedExecutionHandler:饱和策略,当队列满且线程个数达到maximumPoolSize后采取的策略,比如AbortPolicy(抛出异常),CallerRunsPolicy(使用调用者所在的线程来运行任务),DiscardOldestPolicy(调用poll丢弃一个任务,执行当前任务),DiscardPolicy(丢弃,不抛异常)。默认AbortPolicy
  • keepAliveTime:存活时间。如果当前线程池中的线程数量比核心线程数量多,并且是闲置状态,则这些闲置的线程能存活的最大时间
  • TimeUnit:存活时间的时间单位

3 源码分析

3.1 public void execute(Runnable command)

execute方法的作用是提交任务command到线程池执行。
线程池-生产消费模型
ThreadPoolExecutor的实现实际上是一个生产消费模型,当用户添加任务到线程池时,相当于生产者生产元素,线程池里面的worker直接执行任务或者从任务队列里获取任务时,则属于消费者消费元素。

 public void execute(Runnable command) {
        // 如果command为null,则抛出NPE异常
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
	
		// 获取当前线程的状态+线程个数变量的组合值	
        int c = ctl.get();
        // 当前线程池中线程个数是否小于corePoolSize,小于则开启新线程运行
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 当前线程池中线程个数大于corePoolSize,如果线程池处于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);
        }
        // 如果队列满,则新增线程(当前线程大于corePoolSize,小于maximumPoolSize),新增失败,执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

3.2 private boolean addWorker(Runnable firstTask, boolean core)

下面分析新增线程的addWorker方法

  private boolean addWorker(Runnable firstTask, boolean core) {
        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;

			// 标记a
			// 循环CAS增加线程个数
            for (;;) {
                int wc = workerCountOf(c);
                // 如果线程个数超出,返回false
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // CAS增加线程个数,同时只有一个成功
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                // CAS失败了,看线程池状态是否变化了,变化则跳到外层循环尝试重新获取线程池的状态,否则内层循环重新CAS
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

		// 标记b
		// 以下操作说明CAS已经成功
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
        	// 创建worker
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
            	// 加独占锁,为了实现workers同步,可能多个线程调用了线程池的execute方法
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.

					// 重新检查线程池的连接状态,避免在获取锁之前调用了shutdown方法
                    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,目前线程池的最大线程数量
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }

				// 添加任务成功过后,启动线程,处理任务
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

代码比较长,主要解释一下标记a和标记b。
标记a:内层循环的作用就是使用CAS增加线程个数,如果线程个数超出范围,则返回false。没有超出范围,就使用CAS操作设置线程个数,CAS成功则退出双层循环;如果CAS失败了,就查看线程池的状态是否变化了,如果变化了,就再次进入外层循环重新获取线程池状态,否则进入内层循环继续进行CAS尝试。
标记b:获取独占锁,重新检查线程池状态,重新检查是为了避免在获取锁之前其他线程调用了shutdown关闭了线程池。如果线程池已经关闭,则释放锁,新增线程失败。否则添加工作线程到workers,然后释放锁。如果新增工作线程成功,则启动工作线程。

3.3 final void runWorker(Worker w)

用户线程提交任务到线程池后,由worker来执行。
下面是worker的构造函数

 Worker(Runnable firstTask) {
    setState(-1); // inhibit(抑制,阻碍) interrupts until runWorker
    this.firstTask = firstTask;
    this.thread = getThreadFactory().newThread(this); // 创建一个新的线程
}

在构造函数内首先设置Worker的状态为-1,这是为了避免当前worker在调用runWorker方法前被中断(当其他线程用了线程池的shutdownNow时,如果Worker状态>=0则会中断该线程),设置了线程的状态为-1,该线程就不会中断。

final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        // 将status设置为0,允许中断
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            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;
                    // 统计当前Worker完成了多少个任务
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
        	// 执行清理工作
            processWorkerExit(w, completedAbruptly);
        }
    }

如果当前task=null或者调用getTask从任务队列获取的任务返回null,执行processWorkerExit进行清理工作。如果task不为null,获取工作线程内部持有的独占锁,然后执行扩展接口代码在具体任务执行前做一些事情,task.run()具体执行任务,然后执行扩展接口代码在具体任务执行后做一些事情,统计当前worker完成了多少个任务,然后释放锁。
这里在执行具体任务期间加锁,是为了避免在任务执行期间,其他线程调用了shutdown后正在执行的任务被中断(shutdown只会中断当前被阻塞挂起的线程)。
下面解析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.
            // 1.SHUTDOWN 以上的状态,并且workQueue为空
            // 2.STOP以上的状态
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                // 线程数减一
                decrementWorkerCount();
                // 该线程退出
                return null;
            }
			
			// 下面都是RUNNING状态,或SHUTDOWN状态workQueue!=null
			// 计算线程个数
            int wc = workerCountOf(c);

            // Are workers subject to culling?
            // 当allowCoreThreadTimeOut为true或者当前任务数超过核心线程数时,timed为true
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
			// 是否删除超时的线程
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
            	// 如果timed为true说明worker有可能要被关闭
                Runnable r = timed ?
                	// 如果超过keepAliveTime纳秒还没取到任务,就返回null,后面会调用processWorkerExit把worker关闭
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    // timed = false,任务队列为空就阻塞在这里,直到任务队列再有任务
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
}

3.4 private void processWorkerExit(Worker w, boolean completedAbruptly)

	/**
     * If false (default), core threads stay alive even when idle.
     * If true, core threads use keepAliveTime to time out waiting
     * for work.
     */
     // 线程池的成员变量,具体作用看英文注释
    private volatile boolean allowCoreThreadTimeOut;
 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 {
        	// 统计整个线程池完成得任务个数,并从工作集里面删除当前worker
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

		// 尝试设置线程池的状态为TERMINATED,如果当前线程池状态是SHUTDOWN状态并且工作队列为空
		// 或者当时线程池状态是STOP状态,当前线程池里面没有活动线程
        tryTerminate();

	     //当线程池是RUNNING或SHUTDOWN状态时,如果worker是异常结束,直接添加一个线程
        // 线程正常结束, 如果允许对core线程进行超时控制,并且任务队列中有任务, 则保证线程数量>=1
        // 如果不允许对core进行超时控制,则保证线程数量大于等于corePoolSize
        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
            }
            // 如果worker是异常结束,直接添加一个线程
            addWorker(null, false);
        }
    }

统计线程池完成的任务个数,在统计前加了全局锁。把在当前工作线程中完成得任务累加到全局计数器,然后从工作集(workers)中删除当前worker。
如果当前线程池状态是SHUTDOWN状态并且工作队列为空,或者当时线程池状态是STOP状态,当前线程池里面没有活动线程,则设置线程池的状态为TERMINATED。如果设置为了TERMINATED状态,则还需要调用条件变量termination的signAll方法几乎激活所有调用线程池的awaitTermination方法而被阻塞的线程。

3.4 public void shutdown()

调用shutdown方法后,线程池就不会再接受新的任务了,但是工作队列里面的任务还是要执行的。该方法会立刻返回,并不等待队列任务完成之后再返回。

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	// 设置权限检查
            checkShutdownAccess();
            // 设置当前线程池状态为SHUTDOWN,如果已经是SHUTDOWN则直接返回
            advanceRunState(SHUTDOWN);
            // 设置中断标志
            interruptIdleWorkers();
             // hook方法,默认为空,让用户在线程池关闭时可以做一些操作
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        // 尝试将状态变为TERMINATED 
        tryTerminate();
    }

checkShutdownAccess方法检查是否设置了安全管理器,是则看当前调用shutdown命令的线程是否有关闭线程的权限,如果有权限则还要看调用线程是否有中断工作线程的权限。如果没有权限则抛出SecurityException或者NPE。

private void advanceRunState(int targetState) {
   for (;;) {
         int c = ctl.get();
         if (runStateAtLeast(c, targetState) ||
             ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
             break;
     }
}

如果当前线程池的状态>=SHUTDOWN跳出循环,直接返回;否则设置为SHUTDOWN状态。

private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                // 首先看当前线程是否已经中断,如果没有中断,就看线程是否处于空闲状态
            	// 如果能获得线程关联的Worker锁,说明线程处于空闲状态,可以中断
            	// 否则说明线程不能中断
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

设置所有空闲进程的中断标志。这里首先加全局锁,同时只有一个线程可以调用shutdown方法设置中断标志,然后尝试获取Worker自己的锁,获取成功,则设置中断标志。由于正在执行的任务已经获取了锁,所以正在执行的任务没有被中断,这里中断的是阻塞到getTask()方法并试图从队列里面获取任务的线程,就是空闲线程。

final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
	  
         //  当前线程池的状态为以下几种情况时,直接返回:
         //  1. RUNNING,因为还在运行中,不能停止
         //  2. TIDYING或TERMINATED,因为线程池中已经没有正在运行的线程了
         //   3. SHUTDOWN并且等待队列非空,这时要执行完workQueue中的task
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;

			// 只能是以下情形会继续下面的逻辑:结束线程池。
            // 1.SHUTDOWN状态,这时不再接受新任务而且任务队列也空了
            // 2.STOP状态,当调用了shutdownNow方法
            if (workerCountOf(c) != 0) { // Eligible to terminate
                // 如果工作线程数量不为 0,中断线程池中第一个线程
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
            	// 将线程状态设为 TIDYING,如果设置不成功说明线程池的状态发生了变化,需要重试
                // 如果设置成功,则调用terminated方法
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        terminated();
                    } finally {
                    	// 设置当前线程池的状态为TERMINATED 
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

在tryTerminate ()方法中,当工作线程不为0的时候,会去尝试中断线程池中的一个线程,这样做的主要目的在于防止shutdown ()方法的中断信号丢失。
当shutdown ()方法被调用时,会执行interruptIdleWorkers(),此方法会先检查线程是否是空闲状态,如果发现线程不是空闲状态,才会中断线程,中断线程让在任务队列中阻塞的线程醒过来。但是如果在执行interruptIdleWorkers()方法时,线程正在运行,此时并没有被中断;如果线程执行完任务后,然后又去调用了getTask(),这时如果workQueue中没有任务了,调用workQueue.take()时就会一直阻塞。这时该线程便错过了shutdown() 的中断信号,若没有额外的操作,线程会一直处于阻塞的状态。所以每次在工作线程结束时调用tryTerminate方法来尝试中断一个空闲工作线程,避免在队列为空时取任务一直阻塞的情况,弥补了shutdown() 中丢失的信号。

使用CAS设置当前线程池状态为TIDYING,如果设置成功则执行扩张接口terminated在线程池状态变为TERMINATED前做一些事情,然后设置当前线程池状态为TERMINATED。最后调用termination.signalAll()激活因调用条件变量termination的awiat系列方法而被阻塞的所有线程(主要是用户线程)。

3.4 public List shutdownNow()

	public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	// 权限检查
            checkShutdownAccess();
            // 设置当前线程池状态为STOP
            advanceRunState(STOP);
            // 中断所有线程
            interruptWorkers();
            // 将队列任务移动到tasks中
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

首先权限检查,然后设置当前线程池的状态为STOP,随后中断所有线程,中断的所有线程包括:空闲线程和正在执行任务的线程。

private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                // 不管线程是否空闲都执行中断
                w.interruptIfStarted();
        } finally {
            mainLock.unlock();
        }
    }

/**
 * drainQueue()主要作用是清空任务队列,并将队列中剩余的任务返回
 */
private List <Runnable> drainQueue() {
    BlockingQueue <Runnable> q = workQueue;
    ArrayList <Runnable> taskList = new ArrayList < Runnable > ();
    // 该方法会将阻塞队列中的所有项添加到 taskList 中
    // 然后清空任务队列,该方法是线程安全的
    q.drainTo(taskList);
    if (!q.isEmpty()) {
        // 将 List 转换为 数组,传入的 Runnable[0] 用来说明是转为 Runnable 数组
        for (Runnable r: q.toArray(new Runnable[0])) {
            if (q.remove(r))
                taskList.add(r);
        }
    }
    return taskList;
}

/**
 * worker的内部方法
 * 中断(如果运行)
 * shutdownNow时会循环对worker线程执行
 * 且不需要获取worker锁,即使在worker运行时也可以中断
 */
void interruptIfStarted() {
     Thread t;
     // 如果state>=0、t!=null、且t没有被中断
     // new Worker()时state==-1,说明不能中断
      if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
          try {
              t.interrupt();
          } catch (SecurityException ignore) {
          }
      }
 }

3.4 public boolean awaitTermination(long timeout, TimeUnit unit)

当线程调用awaitTermination方法后,当前线程会被阻塞,直到线程池状态变为TERMINATED才返回,或者等待时间超时才返回。

public boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (;;) {
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

以上代码首先获取独占锁,然后在无限循环内部判断当前线程池状态是否至少是TERMINATED状态,如果是则直接返回,否则说明当前线程池里面还有线程在执行,则看设置的超时时间nanos是否小于0,小于0则直接返回,如果大于0则调用条件变量termination的awaitNanos等待nanos时间,期望在这段时间内线程池的状态变为TERMINATED。
如果在调用awaitTermination之前调用shutdown方法,并且在shutdown内部将线程池状态设置为TERMINATED,则termination.awaitNanos方法会返回。
工作线程Worker的runWorker方法内,当工作线程运行结束后,会调用processWorkerExit方法,在processWorkerExit方法内部也会调用tryTerminate方法测试是否应该把当前线程池的状态设置为TERMINATED,如果是,则也会调用termination.signalAll()激活调用线程池的awaitTermination方法而被阻塞的所有线程。
当等待时间超时后,termination.awaitNanos也会返回,这时会重新检查当前线程池状态是否为TERMINATED,如果是直接返回,否则继续阻塞挂起自己。

4 总结

线程池使用了一个Integer类型的原子变量来记录线程池状态和线程池中的线程个数。通过控制线程池的状态来控制任务的执行,每个Worker线程可以执行多个任务。线程池通过线程的复用减少了线程创建和销毁的消耗。
这块代码确实是挺难理解了,笔者也是理解了好长时间,Doug Lea大神用到了AQS和CAS,没有这里的基础,理解起来会相对困难点,希望读这篇文章的人,可以理解笔者的良苦用心,有什么问题,就写在下面的评论里面,笔者会尽力解答的。

5 参考文章

《Java并发之美》
《码出高效》
《Java多线程编程实战》

发布了16 篇原创文章 · 获赞 5 · 访问量 3295

猜你喜欢

转载自blog.csdn.net/qq_32573109/article/details/101536954