画布 1
juc
  A Future represents the result of an asynchronous computation. 这个东西是为了跟踪执行进程用的 Future for tracking progress of one or more asynchronous tasks.
future 即 JUC 设计的异步任务。
  atomic
  locks
    AbstractOwnableSynchronizer
    AbstractQueuedSynchronizer
      工作流程
        管理 sync 的 state
        线程的阻塞和解除阻塞。AQS 中采用了 LockSupport.park(blocker) 来挂起线程，用 LockSupport.unpark(thread) 来唤醒线程。
        阻塞队列 sync queue。因为争抢锁的线程可能很多，但是只能有一个线程拿到锁，其他的线程都必须等待，这个时候就需要一个 queue 来管理这些线程，AQS 用的是一个 FIFO 的队列，就是一个链表，每个 node 都持有后继节点的引用。AQS 采用了 CLH 锁的变体来实现
          CLH锁也是一种基于链表的可扩展、高性能、公平的自旋锁，申请线程只在本地变量上自旋 ，它不断轮询前驱的状态，如果发现前驱释放了锁就结束自旋。
AQS 稍有不同，它是不断轮询：
1. tryAcquire
2. park 或者不 park
3. 释放锁的不一定是前驱，但允许本节点进入待唤醒状态的是前驱。
如果有某个 node 释放锁/signal 察觉到 cancel，它会触发一个 unpark successor 或者 unpark 特定节点的操作
      内部类
        这个条件对象几乎可以说是 Condition 的标准实现，在 JRE 的标准实现里，还有三种几乎不常使用的其他实现
        Node
          static final Node SHARED = new Node();
            // 标识节点当前在共享模式下，注意这个 SHARED 是 static 的
          static final Node EXCLUSIVE = null;
            // 标识节点当前在独占模式下，无多余 tail 的链表天然就是 exclusive 的
          volatile int waitStatus;
            这个值大于0 代表此线程取消了等待
            给 waitStatus 用的状态常量
              static final int CANCELLED = 1;
                此线程取消了争抢这个锁
This node is cancelled due to timeout or interrupt. Nodes never leave this state. In particular, a thread with cancelled node never again blocks. 被取消的线程不会再被阻塞
              static final int SIGNAL = -1;
                当前node的后继节点对应的线程需要被唤醒（unparking）
The successor of this node is (or will soon be) blocked (via park), so the current node must unpark its successor when it releases or cancels. To avoid races, acquire methods must first indicate they need a signal, then retry the atomic acquire, and then, on failure, block.
              static final int CONDITION = -2;
                当前线程在 condition 上做 waiting，在 queue 里
This node is currently on a condition queue. It will not be used as a sync queue node until transferred, at which time the status will be set to 0. (Use of this value here has nothing to do with the other uses of the field, but simplifies mechanics.)
              static final int PROPAGATE = -3;
                the next acquireShared should unconditionally propagate。
下一个操作要从头结点被传播下去，所以这个状态只有头结点才能被设置
A releaseShared should be propagated to other nodes. This is set (for head node only) in doReleaseShared to ensure propagation continues, even if other operations have since intervened.
              0: None of the above
          volatile Node prev;
            前驱节点的引用
Link to predecessor node that current node/thread relies on for checking waitStatus. Assigned during enqueuing, and nulled out (for sake of GC) only upon dequeuing. Also, upon cancellation of a predecessor, we short-circuit while finding a non-cancelled one, which will always exist because the head node is never cancelled: A node becomes head only as a result of successful acquire. A cancelled thread never succeeds in acquiring, and a thread only cancels itself, not any other node.
只有入队的时候才 linked，只有出队的时候才unlinked
          volatile Node next;
            后继节点的引用
Link to the successor node that the current node/thread unparks upon release. Assigned during enqueuing, adjusted when bypassing cancelled predecessors, and nulled out (for sake of GC) when dequeued. The enq operation does not assign next field of a predecessor until after attachment, so seeing a null next field does not necessarily mean that node is at end of queue. However, if a next field appears to be null, we can scan prev's from the tail to double-check. The next field of cancelled nodes is set to point to the node itself instead of null, to make life easier for isOnSyncQueue.
          volatile Thread thread;
            这个就是线程本尊，把它包装成 Node，在 unpark 的时候特别重要。用于在线程 park 和不park的时候作调度的依据。也需要拿来和 aqs 的owner 作比对
在设置 aqs head 和 cancelAcquire 的时候，node 的 thread 会被设置为 null
          这些子主题通常使用 CAS 和 field offset 进行 old value 和 new value 的 swap
        ConditionObject
          /** First node of condition queue. */
private transient Node firstWaiter;
          /** Last node of condition queue. */
private transient Node lastWaiter;
          await()
            制作一个Node，但是入 waitQueue
            fully release 锁
            在自旋里确认是否已经进入 sync queue，如果没有就 park，可以被 unpark 和中断唤醒，如果唤醒，校验是否需要进入 sync 或者已经进入 sync queue，然后退出
              进入 sync queue 的流程比较复杂，有两种 race condition：
1. signal 完成了 transfer：cas 和 enq
            acquireQueued 正式进入求锁流程
          signal()
            把第一个节点放进 sync queue 里
            如果有必要，自己 unpark 那个节点的thread，否则，在释放锁的时候让 unlock 调用 release unpark sync queue 的第一个节点
          Condition 内部也有一个链表管理线程
          这两个方法都是需要 isHeldExclusive() 返回 true 才能调用，否则抛出 IllegalMonitorStateException
对队列的操作，在 AQS 的 state 锁状态变化之前。
需要注意的是，对于锁而言，lock 与 unlock 本身是在一个线程内对称的。但 await 与 signal 本身都在各自线程内执行，但必须【跨线程对称】。
      内部变量
        private transient Thread exclusiveOwnerThread;
          继承自 AbstractOwnableSynchronizer（是aqs 的基类），代表当前持有独占锁的线程，举个最重要的使用例子，因为锁可以重入，reentrantLock.lock()可以嵌套调用多次，所以每次用这个来判断当前线程是否已经拥有了锁 if (currentThread == getExclusiveOwnerThread()) {state++}
通常的带有互斥语义的锁会让 aqs 具有这种标记。
所有的工具都可以通过这个东西来察觉谁在使用这把锁。
这个线程不适用于共享模式工作的同步器。
        private transient volatile Node head;
          头结点，也可以当作当前持有锁的线程。实际上一个节点出队的时候，
        private transient volatile Node tail;
          阻塞的尾节点，每个新的节点进来，都插入到最后，也就形成了一个链表（能够实现公平锁，就可以实现非公平锁，新节点在队尾是一个特别重要的设计）
        private volatile int state;
          代表当前锁的状态，0代表没有被占用，大于 0 代表有线程持有当前锁，这个值可以大于 1，是因为锁可以重入，每次重入都加上 1
这个变量如果换成 long，则会产生另一个 AbstractQueuedLongSynchronizer
        初始化的顺序是 head 到 tail，读取的顺序是 tail 到 head
      工作模式
        exclusive mode
          如果一个线程通过独家模式被获得，其他线程的获得尝试不会成功。
        share mode
          多个线程用共享模式获取这个 aqs，可以（但不必然成功）。
next waiting thread 自己决定在 share mode 下是否也 acquire 一个同步器。
        所有的 mode 共用一个 fifo 队列。同步器的子类只实现某一个 mode（即使它们共用一个队列），它们不用实现某个 mode 不需要的方法
      关键方法
        CLH 的灵魂方法
        自旋的中断 park and check 在这里
        这个方法的目的有 3 个：检查 pred；校正 pred；设置 pred
        这个方法很复杂也很重要，一个队列里面有排这个 Node 前面的nodes则返回true。如果这个队列为空返回 false，这个对象不属于 head 的next也返回false。
        这5个方法是5个子类需要覆写的方法，这样 CLH 和 ConditionObject 才完整。这类框架类关键方法都有个 final 保护起来。
子类可以覆写这五个方法（其他方法不要动），实现自己的锁语义。有很多方法的实现在本类只会抛出 UnsupportedOperationException。
实现这些方法必须线程安全、耗时短和非阻塞-这三个特征指向了 CAS，实现这几个方法是使用 aqs 的标准做法。
Implementations of these methods must be internally thread-safe, and should in general be short and not block. Defining these methods is the <em>only</em> supported
* means of using this class.
        public final void acquire(int arg)
          整个 CLH 的 AQS 版本都在这三个嵌套抽象里
          if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
            入队操作（甚至包括构建链表）全部都在这一个方法里实现
            CLH 最核心、最重要的 spin、park 方法
            private Node addWaiter(Node mode)
              1. 把当前线程包装成 Node
              2. 把 AQS 的尾部取出来，看看是不是为空，如果不是则尝试使用一个快路径入队尾
              3. enq
              4. 返回 node
            acquireQueued
              boolean failed = true; // 设计一个 try 块以前的 flag
              生成一个 try 块
                interrupted = false
                生成一个 for-loop
                  这是在一个判定里写 && 调用
                  条件表达式通常会走完，如果走完了就会经历 park 和把 intterupted 赋值的路径
                  1. final Node p = node.predecessor(); // 这里不是直接访问 prev，加了一个异常抛出机制
                  2. 如果 predecessor 是 head，则 tryAcquire
这里隐含了一个设计，就是不管是不是公平锁，都只有 p 为 head 的节点可以求锁，如果这个阻塞队列是个单链表，其实一次只有一个节点可以求锁
                    这里隐含了一个设计，就是不管是不是公平锁，都只有 p 为 head 的节点可以求锁，如果这个
                    1. 如果这一步成功，则 setHead(当前节点)，完成链表的切换
2. 设置 failed 为 false-保守策略，只有成功路径可以把 failed 去掉。
3. predeccesor 清空 next
4. 返回 interrupted。
                  if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
              在 finally 里检查 failed，如果失败了（异常），cancelAcquire(node)
            selfInterrupt(); 这个方法必定中断
        releaseShared
          if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
        doReleaseShared
          /*
* Ensure that a release propagates, even if there are other
* in-progress acquires/releases. This proceeds in the usual
* way of trying to unparkSuccessor of head if it needs
* signal. But if it does not, status is set to PROPAGATE to
* ensure that upon release, propagation continues.
* Additionally, we must loop in case a new node is added
* while we are doing this. Also, unlike other uses of
* unparkSuccessor, we need to know if CAS to reset status
* fails, if so rechecking.
*/
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
        private Node enq(final Node node);
          构建一个 for-loop，并发的时候竞争入队是可以不用sleep 无限 cas 的
            取 tail，如果 tail 不正常，则 head 不正常，此时初始化链表
              new node 这个 node 本身是 dummy 的，无线程，无 next-也就是 EXCLUSIVE mode
              把这个 node cas set head
              把 cas set 过的 head 赋给 tail
            快速入队
        private static boolean shouldParkAfterFailedAcquire(Node pred, Node node)
          获取 pred 的 waitStatus
          大 if
            如果 ws 为 SIGNAL，则返回 true
            如果 ws 大于 0，实际上意味着这个 pred 已经被取消了，这时候要收窄 pred
            否则，作者断言此时必为 0 或者 -3，也就是初始化和 PROPAGATION，而绝不会为 -2（CONDITION），因为 -2 意味着 Node 不在 sync queue，而在 condition queue 里面，此时通过 CAS 把 pred 的 ws 更新为 SIGNAL，提前进入下一轮循环。
          返回 false
        parkAndCheckInterrupt
          LockSupport.park(this);
          return Thread.interrupted();
        acquireInterruptibly
        acquireSharedInterruptibly
          if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
        doAcquireSharedInterruptibly
          final Node node = addWaiter(Node.SHARED);
          boolean failed = true;
          try
            for (;;)
              final Node p = node.predecessor();
              if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
// 这个setHead 比一般的 acquire 多一步
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
              if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
// 这个方法是 interruptibly 的版本，所以遇到中断应该抛出中断异常
throw new InterruptedException();
            finally {
if (failed)
cancelAcquire(node);
}
        getState()
        setState(int)
          依赖于 volatile
        compareAndSetState(int, int)
          unsafe.compareAndSwapInt(this, stateOffset, expect, update);
这里没有用 atomic 的工具类，而直接使用了 unsafe。unsafe 提供了另一种 CASable 字段的基本实现方法。
Setup to support compareAndSet. We need to natively implement this here: For the sake of permitting future enhancements, we cannot explicitly subclass AtomicInteger, which would be efficient and useful otherwise. So, as the lesser of evils, we natively implement using hotspot intrinsics API. And while we are at it, we do the same for other CASable fields (which could otherwise be done with atomic field updaters).
        private void cancelAcquire(Node node)
          // Ignore if node doesn't exist
if (node == null)
return;
          // 把当前的 node 的线程引用去掉
node.thread = null;
          // Skip cancelled predecessors，操作本节点的 ws时，如要依赖于 predecessor，一定要越过 cancelled predecessor
Node pred = node.prev;
// 在这里也在做一个 prev 的覆盖，只管本废弃节点的 prev 即可，这里可能会存在一个并发问题，如果 pred 的 prev 本身同时也在修改，则 node.prev 会跟着这个 prev 修改变动。这种“越过”操作的本质是废弃不当的 prev，至于 pred.prev 是不是正常，那另当别论
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// 这里的 pred 虽然是当前 node 的prev了，但它的 next 还不是当前 node。这个注释告诉我们，signal 和 cancel 同各式各样的 acquire 是存在竞态条件的
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
Node predNext = pred.next;
          // 在这里只做一个逻辑二分，只解决是不是队尾的问题，不区分队中和队头，如果是队尾则不用管 node next
// If we are the tail, remove ourselves.
if (node == tail && compareAndSetTail(node, pred)) {
// skip 的流程已经告诉我们，node 和 pred 之间的节点都是 CANCELLED 的了
compareAndSetNext(pred, predNext, null);
} else {
// 如果要处理 next，也有两种思路：把 pred 的next link 和 本 node 的 next 连起来，或者直接unpark node 的 next，总之本 node 的 next 得到了很好的处理
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
// 如果 pred 是头，则唤醒它的 successor
unparkSuccessor(node);
}
node.next = node; // help GC
}
        tryAcquire(int)
          断言新state是否合理，不合理则抛出 IllegalMonitorStateException
          cas 比对state
          直接覆写 currentOwnerThread
          返回设置结果
          这一步在 AQS 里通常是抽象的
          这两步并不是原子的，所以比对的时候并不强求比对 currentOwnerThread，但放在一起执行，看似原子
        tryRelease(int)
          断言新state 和 currentOwnerThread 是否合理，不合理则抛出 IllegalMonitorStateException
          设置 state 到 state - 入参
          如果当前的锁是互斥锁，设置 currentOwnerThread 为 null
        tryAcquireShared(int)
        tryReleaseShared(int)
        isHeldExclusively()
          只的有线程内部可以得到这个东西返回 true。这也就意味着我们可以知道自己是不是在临界区内，为 ConditionObject 之类的需要与锁挂钩的解决方案提供了助力。这个方法提供了一个线程内部的“内部视角”。
        hasQueuedPredecessors
          Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
// h == t 则队列为空，返回 false，所以先取反，然后逻辑与，然后先求出前导节点，然后去人这个前导节点不代表当前线程
return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
        实现共享模式需要实现这两个方法，不管是interruptily 还是 uninterruptibly，都使用同样的 release
        实现互斥模式要实现这两种方法
    Lock
    Condition
      这个类型的经典实现，是 Doug Lea 提供的一个生产者和消费者模型
    LockSupport
      使用一个类似 semaphore 的信号量的管理机制，park 寻求 permit，如果求到了park方法会立刻返回，否则会阻塞，unpark 让 permit available，相当于归还 permit（如果没持有也可以归还，支持空归还）。
permit 有个特点就是全员只有一个。
Disables the current thread for thread scheduling purposes unless the permit is available.
If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
Some other thread invokes unpark with the current thread as the target; or
Some other thread interrupts the current thread; or
The call spuriously (that is, for no reason) returns.
This method does not report which of these caused the method to return. Callers should re-check the conditions which caused the thread to park in the first place. Callers may also determine, for example, the interrupt status of the thread upon return.
        park
          Thread t = Thread.currentThread();
// 两步 setBlocker 夹着一个 native park
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
            UNSAFE.putObject(t, parkBlockerOffset, arg);
          恢复的条件为 1：线程调用了unpark; 2:其它线程中断了线程；3：发生了不可预料的事情
所以park是阻塞式的，而且可以通过中断唤醒
          参数是一个对象，比如condition 这个this，或者 aqs这个this
        public static void unpark(Thread thread)
          参数是被park的线程
        这两个方法的内部并不显式管理很多状态，管理状态还是要靠上层 aqs 自己的 state
    阻塞式并发数据结构
      CountDownLatch
        关键方法
          void await() throws InterruptedException
          countDown
            sync.releaseShared(1)
              if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
          构造器
            if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
              // 这样就 state == count 了
setState(count);
        内部类
          sync
            tryAcquireShared
              和其他 acquire 不一样，初始设置 state 类型的 sync，是通过 release 扣减的，不通过 acquire 做加法。
返回结果决定了是否需要入队，是从入队里返回还是直接返回
            tryReleaseShared
              扣减，并返回是否扣减为0，只有扣减为0（而不是一开始为0）才返回真
      CyclicBarrier
        无锁，所以必须在锁里工作
        await
          try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
// 针对有签名但不处理的异常，我们包装为 error
throw new Error(toe); // cannot happen
}
        dowait
          求锁
            取出 generation
            前置检查
              如果已经 broken，抛出 BrokenBarrierException
              如果已中断
                breakBarrier
                InterruptedException
            int index = --count
            检查 index == 0 的情况
              尝试 ranAction
              推动下一代
              返回 index
              如果 ranAction 失败，breakBarrier
            for 循环
              是否超时
                无超时的等待
                有超时的等待，会重写 nanos
                响应中断
                  如果当前代数不变，且没有 broken，breakBarrier。这样可以实现 breakBarrier 的 exactly once
                  否则只是重置我们的中断位
            检查是否 broken，抛出 BrokenBarrierException
            检查 generation是否切换过了（是否发生过 nextGeneration），如果发生过此处返回
            检查是否开启超时以及是否真的发生超时，如果有则抛出 TimeoutException
        breakBarrier
          generation.broken = true
          count = parties
          trip.signalAll()
        nextGeneration
          trip.signalAll()
          count = parties
          generation = new Generation()
        reset
          求锁
            breakBarrier
            nextGeneration
        isBroken
          求锁
            return generation.broken
        getNumberWaiting
          求锁
            return parties - count
      DelayQueue
      PriorityBlockingQueue
      Semaphore
        一个许可池，可以由其他线程 release，类似地铁系统，借一还一不必是同一
      Exchanger
      ReentrantLock
        1.公平体现在抢锁的顺序/时机上，而非线程的调度上。具体地，每个节点抢锁时本来只是 cas AQS 的全局状态和前驱节点的状态而已。【能不能抢锁】本来与这个节点在 FIFO 队列里的位置无关。线程的调度，与公平无关。原生的求锁的限制条件主要是看 predecessor 是不是head，但一般是符合求锁条件的 node 是不会有 queuedPredecessor 的。
2. 引入公平性会降低吞吐，lower，甚至 much lower。
3. 有一些instrumentation 和monitoring 用的 API。
        public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
          Sync
            abstract void lock();
            public void lockInterruptibly()
            final boolean nonfairTryAcquire(int acquires)
              final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
            tryRelease
              int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
// 单线程直接置空即可
setExclusiveOwnerThread(null);
}
setState(c);
// 只有最终 c 为 0 才设置free 为true
return free;
            isHeldExclusively
              // 只有本线程持有锁才返回true，在外部线程看都返回false，即外部线程认为不持有锁
return getExclusiveOwnerThread() == Thread.currentThread();
            getOwner
              很精彩的设计
              // 如果状态为0，则瞬时的 owner 也不足信
return getState() == 0 ? null : getExclusiveOwnerThread();
            getHoldCount()
              很精彩的设计
              return isHeldExclusively() ? getState() : 0; // 只有owner 才能看到 state，和上面正好反过来
            boolean isLocked()
              getState() != 0;
          FairSync
            // 争锁，sync 本身也可以提供锁方法，这两个方法的区别在于 acquire 总有参数而 lock 总没有
final void lock() {
acquire(1);
}
              // 首先调用tryAcquire(1)一下，名字上就知道，这个只是试一试
// 因为有可能直接就成功了呢，也就不需要进队列排队了，
// 对于公平锁的语义就是：本来就没人持有锁，根本没必要进队列等待(又是挂起，又是等待被唤醒的)
if (!tryAcquire(arg) &&
// tryAcquire(arg)没有成功，这个时候需要把当前线程挂起，放到阻塞队列中。
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
                static void selfInterrupt() {
Thread.currentThread().interrupt();
}
            protected final boolean tryAcquire(int acquires)
              final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
          NonFairSync
            lock
              // 注意，这里只做了 state 的短路，没有做关于ownerThread 的判断
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
            boolean tryAcquire(int acquires)
              nonfairTryAcquire(acquires);
  AbstractExecutorService
    执行入口
      public Future<?> submit(Runnable task)
      public <T> Future<T> submit(Runnable task, T result)
      public <T> Future<T> submit(Callable<T> task)
      都把 callable/runnable 包装成 runnable，底层都依赖于 execute
  ThreadPoolExecutor
    提交任务的三个处理策略
      直接执行
        只要 corePoolSize 的线程池没有满，任由线程 idle，也启动更多的 worker thread
      缓冲执行
        否则看看 queue 是不是 full 了，是的话先放在 queue 里，queue 满了增加更多的 worker 线程
      直接拒绝
        通常是直接抛出异常。抛异常通常只有 2 种原因：
          线程池处于关闭状态中
          无法增加线程
    饥渴启动策略
      prestartCoreThread
      prestartAllCoreThreads
      子类可以通过覆写这两个方法来实现饥渴启动，优化线程池冷启动的开销
    阻塞队列的三种思路
      Direct handoffs
        这实际上是 size 为 0 的拥塞队列。
如果没有线程接任务，则任务的提交不能成功。
这必然导致 new thread be constructed。
This policy avoids lockups when handling sets of requests that might have internal dependencies.
任务之间有内在联系，可能导致死锁的时候-这句话的正确理解是父子任务导致的死锁，就必然要求这种策略。handoff 是为了立即执行场景做准备的。
Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks.
它要求无界的 maximumPoolSizes。否则任务的拒绝可能出乎意料。
      Bounded queues
        A bounded queue (for example, an ArrayBlockingQueue) helps prevent resource exhaustion when used with finite maximumPoolSizes。
有界队列和有界的线程池配合使用，提供了 trade off 的空间。
      Unbounded queues
        Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity)
任务只会被 buffered 起来，永远不会有非核心线程被创建出来。
这可以起到流量整形的作用。
无界队列可以堆积，这是一种基本的 buffer 设计思路
      Doug Lea 之所以这么设计，是给我们做设计上 tradeoff 的灵活空间，围绕 finite bounds来做设计。
I/O 会影响吞吐
If tasks frequently block (for example if they are I/O bound), a system may be able to schedule time for more threads than you otherwise allow. Use of small queues generally requires larger pool sizes, which keeps CPUs busier but may encounter unacceptable scheduling overhead, which also decreases throughput.
    拒绝问题
      线程池关闭会导致任务被拒绝
      线程满+队列满也会导致任务被拒绝
      概要
        最常出现的问题，会导致任务的执行状态丢失
        In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.
        In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
        In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
        In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)
    线程池 runState
      RUNNING 能接受新提交的任务，并且也能处理阻塞队列中的任务。
      SHUTDOWN 关闭状态，不再接受新提交的任务，但却可以继续处理阻塞队列中已保存的任务。
      STOP 不能接受新任务，也不处理队列中的任务，会中断正在处理任务的线程。
      TIDYING 所有的任务都已终止了，workerCount (有效线程数) 为0
这个状态的意思不是整理中，而是整理完了
      TERMINATED 在terminated() 方法执行完后进入该状态
    关键成员
      ctl
        包含 runState 和 workerCount。
对这些状态的读写和维护可以在一个 cas 事务里完成。巧妙。
由 atomic 保护
      private final ReentrantLock mainLock = new ReentrantLock();
        Lock held on access to workers set and related bookkeeping.
引入主锁来读写某些东西能够简化相关操作
      private final HashSet<Worker> workers = new HashSet<Worker>();
        这里使用了最简单的 HashSet
      private final Condition termination = mainLock.newCondition();
        Wait condition to support awaitTermination
      private final BlockingQueue<Runnable> workQueue;
        很遗憾，workQueue 是 final 的成员变量，所以通常不能被用户重新设置
      private long completedTaskCount;
        一个计数器，是从 worker 里加总得来的。但只有 worker 退出才能实现加总，所以没有可见性问题，却有最终一致性问题。恐怕只有线程池关闭到最后一刻才是准的。
      private int largestPoolSize;
        最大线程数曾达到的值
      private volatile ThreadFactory threadFactory;
        线程工厂，用户可控
      private volatile RejectedExecutionHandler handler;
        拒绝处理器，用户可控
      private volatile long keepAliveTime;
        纳秒标示的超时时间
      private volatile boolean allowCoreThreadTimeOut;
        缺省为 false，是否允许核心线程也超时
      private volatile int corePoolSize;
        核心线程数
      private volatile int maximumPoolSize;
        最大线程数
      由 final 保护
      线程池内部通过流程控制的参数，由主锁保护
      Doug Lea 把这 7 个变量称为用户控制变量，所以都用 volatile 保护，大部分操作都无锁，但 set 方法里会执行一些有副作用的操作。
其中 maximumSize 有上界检查，coreSize 没有上界检查，所以要先设置 coreSize 而不是 maximumSize。
这两个设值方法和 keepAliveTime 的变化都会导致额外的 worker 数量增减。
很遗憾，workQueue 是 final 的，不能被变动。
    执行入口
      public void execute(Runnable command)
        If fewer than corePoolSize threads are running, try to start a new thread with the given command as its first task.
如果当前的 workerCount 小于核心线程数，尝试添加worker（并不必然成功），把 runnable 做成它的 firstTask
        先插入缓冲队列，如果插入成功，则再确认是不是 addWorker
        获取 workerCount
        if (workerCountOf(c) < corePoolSize)
          if (addWorker(command, true))
return;
这里这个 true 就是增加核心线程的意思
          如果没有立即返回，则刷新 workerCount c = ctl.get();
        if (isRunning(c) && workQueue.offer(command))
这里试图获取刷新过的 c，并且做一个非阻塞的对 workQueue 的插入
          获取一个 recheck 的状态 int recheck = ctl.get();
          if (! isRunning(recheck) && remove(command))
reject(command);
如果此时线程池不再运行，且出队列成功，则拒绝这个任务
          else if (workerCountOf(recheck) == 0)
addWorker(null, false);
如果线程池还在运行，但 workerCount 为 0，则增加非核心线程
        else if (!addWorker(command, false))
reject(command);
这里还在尝试增加非核心线程，如果实在不行就拒绝了
    方法钩子
      beforeExecute(Thread, Runnable)
      afterExecute(Runnable, Throwable)
      terminated
        can be overridden to perform any special processing that needs to be done once the Executor has fully terminated.
可以用来做线程池清理
      remove
        可以把任务从 workQueue 里面移出，还附带一个关闭的尝试
      purge
        if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
it.remove();
尝试把所有已取消的任务移出队列
      called before and after execution of each task. These can be used to manipulate the execution environment; for example, reinitializing ThreadLocals, gathering statistics, or adding log entries.
可以被用来重新调整执行环境
    关键内部类
      Worker
        机会主义地实现了 AQS
          之所以这样做，是为了防止可重入锁的重入，这样每个调用只会调用线程池控制方法（setCorePoolSize）一次。
        实现了 Runnable
        关键成员
          final Thread thread;
            Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
          Runnable firstTask;
            Initial task to run. Possibly null.
          volatile long completedTasks;
            Per-thread task counter
    统计结果
      getPoolSize
        当前线程数，在主锁内访问，比较准
      getActiveCount
        获取当前的 worker 处于 locked 状态的总数（证明正在内部执行任务），比较准
      getLargestPoolSize
        在主锁内访问 largestPoolSize
      getTaskCount
        Returns the approximate total number of tasks that have ever been scheduled for execution. 不准、近似值
在主锁内访问
      getCompletedTaskCount
        Returns the approximate total number of tasks that have completed execution
在主锁内访问
      线程池大部分工作线程只有在退出时需要访问主锁，所以不频繁地调用这些统计接口并不会降低吞吐
  ThreadFactory
    线程名
    优先级
    线程组
    是否 daemon
  Future
    boolean cancel(boolean mayInterruptIfRunning)
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
  RunnableFuture
    增加了 run 方法
  FutureTask
    一个可取消的异步计算任务。
A cancellable asynchronous computation
      关键方法
        set
        setException
        cancel
      关键成员
        private volatile int state;
          核心驱动状态，cas 和阻塞都围绕它来构建
        private Callable<V> callable;
          在执行完成后不可获取（除非），执行过程中的异常会进入 outcome
        private Object outcome;
          // non-volatile, protected by state reads/writes
/** The result to return or exception to throw from get() */
因为容纳了异常和 V，所以 casting 的时候必然会导致 warning
        private volatile Thread runner;
          维护它可以保证 exactly once 的幂等，也可以保证可以准确中断它
        private volatile WaitNode waiters;