ThreadPoolExecutor的实现中,使用到了CAS、AbstractQueuedSynchronizer、ReentrantLock。 1、主要构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) 1)corePoolSize,核心线程数 2)maximumPoolSize,最大线程数 3)keepAliveTime,多余核心线程数的其余线程的空闲时间。 4)unit,针对keepAliveTime的单位 5)workQueue,任务阻塞队列,使用较多的是:ArrayBlockingQueue 6)threadFactory,创建线程的工厂,可以自定义。 7)handler,当阻塞队列慢,且没有空闲线程,这个时候提交任务时,采取的策略。默认策略是AbortPolicy(直接抛出异常) 2、主要方法 1)public void execute(Runnable command) 在将来的某个时间执行指定任务command,可能在新线程中或者在现有池线程中执行该任务。 public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); 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:添加线程并处理任务 workQueue.offer:为入阻塞队列 reject(command):拒绝策略处理该任务。 注意,在workerCountOf(recheck) == 0时执行addWorker(null, false);这是为了保证线程池在RUNNING状态下必须要有一个线程来执行任务。 这里有个算法来处理当前任务: 如果workerCount < corePoolSize,则创建并启动一个线程来执行新提交的任务; 如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中; 如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务; 如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。 2)private boolean addWorker(Runnable firstTask, boolean core) 添加线程并处理任务,firstTask为添加的第一个任务,新增线程时,会判断当前线程数是否少于corePoolSize,如果core=true,则与corePoolSize比较,否则为false,与maximumPoolSize比较。 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; 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);//创建一个orker final Thread t = w.thread; 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()); 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) { t.start();//执行任务。 workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; } 分析: 核心语句:t.start();执行线程,该线程从Worker类里取得,下面先分析下Worker类。 3)分析Worker private final class Worker extends AbstractQueuedSynchronizer implements Runnable { private static final long serialVersionUID = 6138294804551838833L; final Thread thread; Runnable firstTask; volatile long completedTasks; 可见Worker类实现了Runnable。关于它的构造函数如下: Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } 在创建线程时,入参是this,也就是说当执行thread.start的时候,将执行Worker下的run方法。 也就是说,在addWorker里的核心语句t.start();将执行的是Worker下的run方法,Worker的run方法如下: public void run() { runWorker(this); } 4)final void runWorker(Worker w) ThreadPoolExecutor的方法 final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; 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; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } } 分析: while语句中的判断,首先会取Worker.firstTask来执行,如果Worker.firstTask处理完,再getTask()来获取队列里的其他任务来处理。 任务处理语句:task.run(); 可以看到,在执行任务前后,会调用beforeExecute(wt, task);afterExecute(task, thrown);这个可用于自定义扩展,在执行线程任务前后的处理工作。 处理完任务后,删除Worker,退出线程:processWorkerExit(w, completedAbruptly); 5)private Runnable getTask() ThreadPoolExecutor的方法,从阻塞队列中,取任务。 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. if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); // Are workers subject to culling? boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { 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; } } } 分析: 核心语句: Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); 去任务的时候,这里有个timed的判断,即如果配置了核心线程允许超时 或者 当前线程数已经大于 corePoolSize, 则通过poll方法取任务:workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS), 否则,通过take方法取任务:workQueue.take()。 以ArrayBlockingQueue类为例,poll和take的区别如下: public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) { if (nanos <= 0) return null; nanos = notEmpty.awaitNanos(nanos); } return dequeue(); } finally { lock.unlock(); } } public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return dequeue(); } finally { lock.unlock(); } } 可以看到,poll取任务时,awaitNanos有时间限制,当时间超过nanos时,队列里还是空的,则返回null。 而take取任务时,notEmpty.await(),当队列为空时,方法会一直阻塞,直到取出队列的任务。 6)private void processWorkerExit(Worker w, boolean completedAbruptly) ThreadPoolExecutor的方法, 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);//从Worker集合中移除当前worker } 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); } } 分析: 从Worker集合中移除当前worker后,调用tryTerminate(),该tryTerminate主要用于中断一个空闲的线程。 7) final void tryTerminate() ThreadPoolExecutor的方法, final void tryTerminate() { for (;;) { int c = ctl.get(); if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())) return; 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 } } 分析: 中断线程核心语句:interruptIdleWorkers(ONLY_ONE);仅且只中断一个。 下面还有一句terminated();该方法目前没有实现,用于扩展,子类可以自定义实现。 8)private void interruptIdleWorkers(boolean onlyOne) ThreadPoolExecutor的方法,参数onlyOne=true,表示仅中断一个,否则中断所有的空闲线程。 private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread; if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } } 分析: 核心语句: t.interrupt(); 只是设置该线程的中断标志位,当其他逻辑拿到线程中断标志位,做相应的处理, 比如说,getTask里的方法取队列时,调用了await方法,当收到中断标志位后,会抛出InterruptedException异常而中止阻塞。
对ThreadPoolTaskExecutor的理解
最新推荐文章于 2022-02-28 18:12:22 发布