java Executors源码简析
来源:互联网 发布:淘宝店铺怎么登录 编辑:程序博客网 时间:2024/06/15 02:32
package a160229;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorsTest {public static void main(String[] args) {ExecutorService threadPool = Executors.newFixedThreadPool(5);for(int i=1; i<=10; i++) {threadPool.execute(new Task(i));}threadPool.shutdown();while(!threadPool.isTerminated());System.out.println("all over!");}}class Task implements Runnable {int id;Task(int id) {this.id = id;}@Overridepublic void run() {try {Thread.sleep(new Random().nextInt(10)*1000);} catch (InterruptedException e1) {// TODO Auto-generated catch block//e1.printStackTrace();System.out.println("task" + id + "is interrupted");}System.out.println("task" + id + " is running ");try {Thread.sleep(new Random().nextInt(10)*1000);} catch (InterruptedException e) {// TODO Auto-generated catch block//e.printStackTrace();System.out.println("task" + id + "is interrupted");
让我们来以这段代码为例简单分析Executor源码。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
newFixedThreadPool 是创建一个固定大小的线程池,固定线程数为nThreads,如果当前线程数不足以满足当前任务数,未被线程受理的任务会进入一个队列(这里是LinkedBlokingQueue,下一篇文章分析这个队列)。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
构造函数中需要说明的形参,corePoolSize是在未设置allowCoreThreadTimeOut的情况下,池中所维持的线程数,即便其中线程是空闲状态;maximumPoolSize是池所允许的最大线程数。
如此,一个线程池就建好了,当然此时还没有线程。
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); }
让我们来看ctl是什么玩意
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; 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 private static int More ...runStateOf(int c) { return c & ~CAPACITY; } private static int More ...workerCountOf(int c) { return c & CAPACITY; } private static int More ...ctlOf(int rs, int wc) { return rs | wc; }
Ctl就是control,是一个32bit二进制数(一个int),高3位代表了线程池的状态(RUNNING等),低29位表示最大线程数(非用户设置数,当用户设置数大于此数时,用户设置数并不会被重置,而是以此数为标准)。
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); 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; }
addWorker就是要向池中添加线程了,其中会有池状态检查(主要包括线程池是否处于要关闭状态、池中线程数是否到达阈值等)。
workers.add(w)就是向池(workers是一个hashset)中放入工作线程,而后t.start()便启动了工作线程,这里t(thread)和w(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 firstTask) { setState(-1); // inhibit interrupts until runWorker 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(); // 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); } }}
可以看出runWorker才是工作线程真正的执行代码,其中task.run就是我们定义的任务的执行,执行过程中同样会检查线程池状态,如下。
if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt();
当线程池处于STOP状态时,线程会被标记打断,但当前线程会继续执行,也即当前任务会继续执行完。while (task != null || (task = getTask()) != null)中,getTask时如果状态为STOP,即使队列中有任务,其也会返回null,这就会使得runWorker 方法中的for循环被终止,从而执行后面的processWorkerExit
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); } }
这里的关键方法就是workers.remove,此后相应worker已被移除workers(hashset)。
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))) {//设置TIDYING try { terminated(); } finally { ctl.set(ctlOf(TERMINATED, 0));//执行完terminated后,池变为TERMINATED状态 termination.signalAll();//Wakes up all waiting threads. } return; } } finally { mainLock.unlock(); } // else retry on failed CAS } }
tryTerminate();会试图STOP-> TERMINATED
最后看一下shutdown方法
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(SHUTDOWN);//池状态变为SHUTDOWN interruptIdleWorkers();//将所有worker标记打断 onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
while(!threadPool.isTerminated()),isTerminated就是检查线程池状态(ctl的值)是否为TERMINATED
- java Executors源码简析
- Java源码阅读之Executors
- Java Executors框架的源码理解
- Java Executors
- java Executors
- JDK源码阅读 java.util.concurrent.Executors相关分析
- java源码分析系列一 线程池Executors
- java多线程(3)---Executors线程池源码分析
- jdk 源码分析(13)java ExecutorService 和Executors
- Executors源码解析
- Java Executors(线程池)
- java Executors(线程池)
- Java Executors(线程池)
- 黑马程序员 java Executors
- Java Executors(线程池)
- Java多线程-Executors
- Executors线程池--java
- Java Executors(线程池)
- 几种搜索引擎算法
- 图之邻接表
- [Git]第六回 Git标签
- 仿微信群头像,自定义控件
- 百宝云开源商业化完整注册码系统——商业脚本作者必备系统
- java Executors源码简析
- Android - 重要知识点
- soj 2796 Letter Deletion LCS
- 阿里java常见面试题
- SCM代码的学习与优化
- IntentService的原理及使用
- 一种均匀分布不模糊的波纹效果实现。
- 在mac下安装mysql时 Access denied for user 'root'@'localhost' (using password: YES) 如何解决
- Hadoop的启动与停止