线程池-ThreadPoolExecutor

线程池

2021-01-08

线程池的概念

我们可以把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。只要池里有空闲的线程,任务就会分配给一个线程执行。在线程池的内部,任务被插入一个阻塞队列(Blocking Queue ),线程池里的线程会去取这个队列里的任务。当一个新任务插入队列时,一个空闲线程就会成功的从队列中取出任务并且执行它。

image.png

以上是线程池的基本概念和执行流程,实际上根据线程池的类型不同,执行顺序有些许差异

JDK提供的线程池

Executor.png
  • 接口 Executor 顶层接口
  • 接口 ExecutorService 定义接触方法
  • 抽象类 AbstractExecutorService 提供重要方法的实现submit,,是抽象类,但没有抽象方法。
  • 接口 ScheduledExecutorService 类似于定时任务的线程池实现接口 继承于 ExecutorService
  • 类 ThreadPoolExecutor 重点类,是线程池实现的重点,
  • 类 Executors 工具类,提供各种线程池的创建工具

Executor

package java.util.concurrent;

public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

Executor是顶层接口。提供execute方法,

ExecutorService

  • 是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法,返回 Future 对象,以及可跟踪一个或多个异步任务执行状况返回Future的方法;
    可以调用ExecutorService的shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。因此我们一般用该接口来实现和管理多线程。
  • 通过 ExecutorService.submit() 方法返回的 Future 对象,可以调用isDone()方法查询Future是否已经完成。当任务完成时,它具有一个结果,你可以调用get()方法来获取该结果。你也可以不用isDone()进行检查就直接调用get()获取结果,在这种情况下,get()将阻塞,直至结果准备就绪,还可以取消任务的执行。Future 提供了 cancel() 方法用来取消执行 pending 中的任务。
public interface ExecutorService extends Executor {
    <!--停止线程池,状态设置为SHUTDOWN,并且不在接受新的任务,已经提交的任务会继续执行-->
    void shutdown();
    <!--停止线程池,状态设置为STOP,不在接受先任务,尝试中断正在执行的任务,返回还未执行的任务-->
    List<Runnable> shutdownNow();
    <!--是否是SHUTDOWN状态-->
    boolean isShutdown();
    <!--是否所有任务都已经终止-->
    boolean isTerminated();
    <!--超时时间内,去等待任务执行任务-->
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;   
    <!--Callable 去提交任务-->
    <T> Future<T> submit(Callable<T> task);
    <!--Runnable 去提交任务-->
    <T> Future<T> submit(Runnable task, T result);
    <!--Runnable 去提交任务-->
    Future<?> submit(Runnable task);
    
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

AbstractExecutorService

参考 ThreadPoolExecutor是怎么去执行一个任务的?
AbstractExecutorService是一个抽象类,实现了ExecutorService接口,这边顺带说下,为什么java 源码里面存在大量 抽象类实现接口,然后类再继承抽象类,为什么类不直接实现接口呢?还要套一层呢,之前我也不明白,后来我才清楚,抽象类去实现接口,就是去实现一些公共的接口方法,这样类再次去实现接口的时候,只要关心我不同的实现就好了,因为 我们知道接口的实现类不止一个,抽象类就是把这些要实现接口的类的公共的实现再次抽取出来,避免了大量的重复实现,尤其List,Set 接口 你看下 几乎都有响应的抽象类实现!


package java.util.concurrent;
import java.util.*;

public abstract class AbstractExecutorService implements ExecutorService {

  
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

 
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

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

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

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

   
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (tasks == null)
            throw new NullPointerException();
        int ntasks = tasks.size();
        if (ntasks == 0)
            throw new IllegalArgumentException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // Start one task for sure; the rest incrementally
            futures.add(ecs.submit(it.next()));
            --ntasks;
            int active = 1;

            for (;;) {
                Future<T> f = ecs.poll();
                if (f == null) {
                    if (ntasks > 0) {
                        --ntasks;
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    else if (active == 0)
                        break;
                    else if (timed) {
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                if (f != null) {
                    --active;
                    try {
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }
    }

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
        try {
            return doInvokeAny(tasks, false, 0);
        } catch (TimeoutException cannotHappen) {
            assert false;
            return null;
        }
    }

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
    }

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks) {
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));

            final long deadline = System.nanoTime() + nanos;
            final int size = futures.size();

            // Interleave time checks and calls to execute in case
            // executor doesn't have any/much parallelism.
            for (int i = 0; i < size; i++) {
                execute((Runnable)futures.get(i));
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L)
                    return futures;
            }

            for (int i = 0; i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    if (nanos <= 0L)
                        return futures;
                    try {
                        f.get(nanos, TimeUnit.NANOSECONDS);
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

}

ScheduledExecutorService

了解这个体系就好,本次不是重点

Executors

用来创建各类线程池的

public static class Executors {

        //创建固定线程数量的线程池。
        //该线程池中线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行,若没有,则新的任务会被暂存在一个任务队列中
        // 待有线程空闲时,便处理在任务队列中的任务
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>());
        }


        // 创建单线程的的线程池
        // 该方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲时,按先入先出的顺序执行队列的任务
        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                    (new ThreadPoolExecutor(1, 1,
                            0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>()));
        }

        // 该方法返回一个可根据实际情况调整线程数量的线程池,线程池的线程数量不固定,但若有空闲线程可以复用,则优先使用可复用的线程。
        // 若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务,所有线程都在当前任务执行完毕后,将返回线程池进行复用。
        public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                    60L, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>());
        }

        // 该方法返回一个 ScheduledExecutorService 对象,线程池大小为1。 
        // ScheduledExecutorService 接口在 ExecutorService 接口之上扩展了在指定时间执行某任务的功能,如在某个固定的延时之后执行,或者周期性执行某个任务
        public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
            return new java.util.concurrent.Executors.DelegatedScheduledExecutorService
                    (new ScheduledThreadPoolExecutor(1));
        }

        // 该方法也返回一个 ScheduledExecutorService 对象。但该线程池可以指定线程数量。
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
        }
    }

ThreadPoolExecutor

概念

TODO

源码解析



package java.util.concurrent;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;


public class ThreadPoolExecutor extends AbstractExecutorService {

    //高3位:表示当前线程池运行状态   除去高3位之后的低位:表示当前线程池中所拥有的线程数量
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    //表示在ctl中,低COUNT_BITS位 是用于存放当前线程数量的位。
    private static final int COUNT_BITS = Integer.SIZE - 3;
    //低COUNT_BITS位 所能表达的最大数值。 000 11111111111111111111 => 5亿多。
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // runState is stored in the high-order bits
    //111 000000000000000000  转换成整数,其实是一个负数
    private static final int RUNNING    = -1 << COUNT_BITS;
    //000 000000000000000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    //001 000000000000000000
    private static final int STOP       =  1 << COUNT_BITS;
    //010 000000000000000000
    private static final int TIDYING    =  2 << COUNT_BITS;
    //011 000000000000000000
    private static final int TERMINATED =  3 << COUNT_BITS;

    // Packing and unpacking ctl
    //获取当前线程池运行状态
    //~000 11111111111111111111 => 111 000000000000000000000
    //c == ctl = 111 000000000000000000111
    //111 000000000000000000111
    //111 000000000000000000000
    //111 000000000000000000000
    private static int runStateOf(int c)     { return c & ~CAPACITY; }

    //获取当前线程池线程数量
    //c == ctl = 111 000000000000000000111
    //111 000000000000000000111
    //000 111111111111111111111
    //000 000000000000000000111 => 7
    private static int workerCountOf(int c)  { return c & CAPACITY; }

    //用在重置当前线程池ctl值时  会用到
    //rs 表示线程池状态   wc 表示当前线程池中worker(线程)数量
    //111 000000000000000000
    //000 000000000000000111
    //111 000000000000000111
    private static int ctlOf(int rs, int wc) { return rs | wc; }


    //比较当前线程池ctl所表示的状态,是否小于某个状态s
    //c = 111 000000000000000111 <  000 000000000000000000 == true
    //所有情况下,RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED
    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }

    //比较当前线程池ctl所表示的状态,是否大于等于某个状态s
    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }

    //小于SHUTDOWN 的一定是RUNNING。 SHUTDOWN == 0
    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

    /**
     * Attempts to CAS-increment the workerCount field of ctl.
     */
    //使用CAS方式 让ctl值+1 ,成功返回true, 失败返回false
    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

    //使用CAS方式 让ctl值-1 ,成功返回true, 失败返回false
    private boolean compareAndDecrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect - 1);
    }

    //将ctl值减一,这个方法一定成功
    private void decrementWorkerCount() {
        //这里会一直重试,直到成功为止。
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }

 
    //任务队列,当线程池中的线程达到核心线程数量时,再提交任务 就会直接提交到 workQueue
    //workQueue  instanceOf ArrayBrokingQueue   LinkedBrokingQueue  同步队列
    private final BlockingQueue<Runnable> workQueue;

 
    //线程池全局锁,增加worker 减少 worker 时需要持有mainLock , 修改线程池运行状态时,也需要。
    private final ReentrantLock mainLock = new ReentrantLock();

    /**
     * Set containing all worker threads in pool. Accessed only when
     * holding mainLock.
     */
    //线程池中真正存放 worker->thread 的地方。
    private final HashSet<Worker> workers = new HashSet<Worker>();


    //当外部线程调用  awaitTermination() 方法时,外部线程会等待当前线程池状态为 Termination 为止。
    //等待是如何实现的? 就是将外部线程 封装成 waitNode 放入到 Condition 队列中了, waitNode.Thread 就是外部线程,会被park掉(处于WAITING状态)。
    //当线程池 状态 变为 Termination时,会去唤醒这些线程。通过 termination.signalAll() ,唤醒之后这些线程会进入到 阻塞队列,然后头结点会去抢占mainLock。
    //抢占到的线程,会继续执行awaitTermination() 后面程序。这些线程最后,都会正常执行。
    //简单理解:termination.await() 会将线程阻塞在这。
    //         termination.signalAll() 会将阻塞在这的线程依次唤醒
    private final Condition termination = mainLock.newCondition();

 
    //记录线程池生命周期内 线程数最大值
    private int largestPoolSize;

    //记录线程池所完成任务总数 ,当worker退出时会将 worker完成的任务累积到completedTaskCount
    private long completedTaskCount;

  
 
    //创建线程时会使用 线程工厂,当我们使用 Executors.newFix...  newCache... 创建线程池时,使用的是 DefaultThreadFactory
    //一般不建议使用Default线程池,推荐自己实现ThreadFactory
    private volatile ThreadFactory threadFactory;

 
    //拒绝策略,juc包提供了4中方式,默认采用 Abort..抛出异常的方式。
    private volatile RejectedExecutionHandler handler;

 
    //空闲线程存活时间,当allowCoreThreadTimeOut == false 时,会维护核心线程数量内的线程存活,超出部分会被超时。
    //allowCoreThreadTimeOut == true 核心数量内的线程 空闲时 也会被回收。
    private volatile long keepAliveTime;


    //控制核心线程数量内的线程 是否可以被回收。true 可以,false不可以。
    private volatile boolean allowCoreThreadTimeOut;

 
    //核心线程数量限制。
    private volatile int corePoolSize;

 
    //线程池最大线程数量限制。
    private volatile int maximumPoolSize;


    //缺省拒绝策略,采用的是AbortPolicy 抛出异常的方式。
    private static final RejectedExecutionHandler defaultHandler =
            new AbortPolicy();


    private static final RuntimePermission shutdownPerm =
            new RuntimePermission("modifyThread");

    /* The context to be used when executing the finalizer, or null. */
    private final AccessControlContext acc;


    private final class Worker
            extends AbstractQueuedSynchronizer
            implements Runnable
    {
        //Worker采用了AQS的独占模式
        //独占模式:两个重要属性  state  和  ExclusiveOwnerThread
        //state:0时表示未被占用 > 0时表示被占用   < 0 时 表示初始状态,这种情况下不能被抢锁。
        //ExclusiveOwnerThread:表示独占锁的线程。
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** Thread this worker is running in.  Null if factory fails. */
        //worker内部封装的工作线程
        final Thread thread;
        /** Initial task to run.  Possibly null. */
        //假设firstTask不为空,那么当worker启动后(内部的线程启动)会优先执行firstTask,当执行完firstTask后,会到queue中去获取下一个任务。
        Runnable firstTask;

        /** Per-thread task counter */
        //记录当前worker所完成任务数量。
        volatile long completedTasks;

        /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        //firstTask可以为null。为null 启动后会到queue中获取。
        Worker(Runnable firstTask) {
            //设置AQS独占模式为初始化中状态,这个时候 不能被抢占锁。
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            //使用线程工厂创建了一个线程,并且将当前worker 指定为 Runnable,也就是说当thread启动的时候,会以worker.run()为入口。
            this.thread = getThreadFactory().newThread(this);
        }

        /** Delegates main run loop to outer runWorker  */
        //当worker启动时,会执行run()
        public void run() {
            //ThreadPoolExecutor->runWorker() 这个是核心方法,等后面分析worker启动后逻辑时会以这里切入。
            runWorker(this);
        }

        // Lock methods
        //
        // The value 0 represents the unlocked state.
        // The value 1 represents the locked state.
        //判断当前worker的独占锁是否被独占。
        //0 表示未被占用
        //1 表示已占用
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }


        //尝试去占用worker的独占锁
        //返回值 表示是否抢占成功
        protected boolean tryAcquire(int unused) {
            //使用CAS修改 AQS中的 state ,期望值为0(0时表示未被占用),修改成功表示当前线程抢占成功
            //那么则设置 ExclusiveOwnerThread 为当前线程。
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }

            return false;
        }

        //外部不会直接调用这个方法 这个方法是AQS 内调用的,外部调用unlock时 ,unlock->AQS.release() ->tryRelease()
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        //加锁,加锁失败时,会阻塞当前线程,直到获取到锁位置。
        public void lock()        { acquire(1); }

        //尝试去加锁,如果当前锁是未被持有状态,那么加锁成功后 会返回true,否则不会阻塞当前线程,直接返回false.
        public boolean tryLock()  { return tryAcquire(1); }

        //一般情况下,咱们调用unlock 要保证 当前线程是持有锁的。
        //特殊情况,当worker的state == -1 时,调用unlock 表示初始化state 设置state == 0
        //启动worker之前会先调用unlock()这个方法。会强制刷新ExclusiveOwnerThread == null State==0
        public void unlock()      { release(1); }

        //就是返回当前worker的lock是否被占用。
        public boolean isLocked() { return isHeldExclusively(); }

        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }

    /*
     * Methods for setting control state
     */

    /**
     * Transitions runState to given target, or leaves it alone if
     * already at least the given target.
     *
     * @param targetState the desired state, either SHUTDOWN or STOP
     *        (but not TIDYING or TERMINATED -- use tryTerminate for that)
     */
    private void advanceRunState(int targetState) {
        //自旋
        for (;;) {
            int c = ctl.get();
            //条件成立:假设targetState == SHUTDOWN,说明 当前线程池状态是 >= SHUTDOWN
            //条件不成立:假设targetState == SHUTDOWN ,说明当前线程池状态是RUNNING。
            if (runStateAtLeast(c, targetState) ||
                    ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

  
    final void tryTerminate() {
        //自旋
        for (;;) {
            //获取最新ctl值
            int c = ctl.get();
            //条件一:isRunning(c)  成立,直接返回就行,线程池很正常!
            //条件二:runStateAtLeast(c, TIDYING) 说明 已经有其它线程 在执行 TIDYING -> TERMINATED状态了,当前线程直接回去。
            //条件三:(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())
            //SHUTDOWN特殊情况,如果是这种情况,直接回去。得等队列中的任务处理完毕后,再转化状态。
            if (isRunning(c) ||
                    runStateAtLeast(c, TIDYING) ||
                    (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;

            //什么情况会执行到这里?
            //1.线程池状态 >= STOP
            //2.线程池状态为 SHUTDOWN 且 队列已经空了

            //条件成立:当前线程池中的线程数量 > 0
            if (workerCountOf(c) != 0) { // Eligible to terminate
                //中断一个空闲线程。
                //空闲线程,在哪空闲呢? queue.take() | queue.poll()
                //1.唤醒后的线程 会在getTask()方法返回null
                //2.执行退出逻辑的时候会再次调用tryTerminate() 唤醒下一个空闲线程
                //3.因为线程池状态是 (线程池状态 >= STOP || 线程池状态为 SHUTDOWN 且 队列已经空了) 最终调用addWorker时,会失败。
                //最终空闲线程都会在这里退出,非空闲线程 当执行完当前task时,也会调用tryTerminate方法,有可能会走到这里。
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            //执行到这里的线程是谁?
            //workerCountOf(c) == 0 时,会来到这里。
            //最后一个退出的线程。 咱们知道,在 (线程池状态 >= STOP || 线程池状态为 SHUTDOWN 且 队列已经空了)
            //线程唤醒后,都会执行退出逻辑,退出过程中 会 先将 workerCount计数 -1 => ctl -1。
            //调用tryTerminate 方法之前,已经减过了,所以0时,表示这是最后一个退出的线程了。

            final ReentrantLock mainLock = this.mainLock;
            //获取线程池全局锁
            mainLock.lock();
            try {
                //设置线程池状态为TIDYING状态。
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        //调用钩子方法
                        terminated();
                    } finally {
                        //设置线程池状态为TERMINATED状态。
                        ctl.set(ctlOf(TERMINATED, 0));
                        //唤醒调用 awaitTermination() 方法的线程。
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                //释放线程池全局锁。
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }


    private void checkShutdownAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(shutdownPerm);
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            } finally {
                mainLock.unlock();
            }
        }
    }

    /**
     * Interrupts all threads, even if active. Ignores SecurityExceptions
     * (in which case some threads may remain uninterrupted).
     */
    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        //获取线程池全局锁
        mainLock.lock();
        try {
            //遍历所有worker
            for (Worker w : workers)
                //interruptIfStarted() 如果worker内的thread 是启动状态,则给它一个中断信号。。
                w.interruptIfStarted();
        } finally {
            //释放线程池全局锁
            mainLock.unlock();
        }
    }


    //onlyOne == true 说明只中断一个线程 ,false 则中断所有线程
    //共同前提,worker是空闲状态。
    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        //持有全局锁
        mainLock.lock();
        try {
            //迭代所有worker
            for (Worker w : workers) {
                //获取当前worker的线程 保存到t
                Thread t = w.thread;
                //条件一:条件成立:!t.isInterrupted()  == true  说明当前迭代的这个线程尚未中断。
                //条件二:w.tryLock() 条件成立:说明当前worker处于空闲状态,可以去给它一个中断信号。 目前worker内的线程 在 queue.take() | queue.poll()
                //阻塞中。因为worker执行task时,是加锁的!
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        //给当前线程中断信号..处于queue阻塞的线程,会被唤醒,唤醒后,进入下一次自旋时,可能会return null。执行退出相关的逻辑。
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        //释放worker的独占锁。
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }

        } finally {
            //释放全局锁。
            mainLock.unlock();
        }
    }


    private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }

    private static final boolean ONLY_ONE = true;

 
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

    /**
     * Performs any further cleanup following run state transition on
     * invocation of shutdown.  A no-op here, but used by
     * ScheduledThreadPoolExecutor to cancel delayed tasks.
     */
    void onShutdown() {
    }


    final boolean isRunningOrShutdown(boolean shutdownOK) {
        int rs = runStateOf(ctl.get());
        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
    }


    private List<Runnable> drainQueue() {
        BlockingQueue<Runnable> q = workQueue;
        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
        q.drainTo(taskList);
        if (!q.isEmpty()) {
            for (Runnable r : q.toArray(new Runnable[0])) {
                if (q.remove(r))
                    taskList.add(r);
            }
        }
        return taskList;
    }


    //firstTask 可以为null,表示启动worker之后,worker自动到queue中获取任务.. 如果不是null,则worker优先执行firstTask
    //core 采用的线程数限制 如果为true 采用 核心线程数限制  false采用 maximumPoolSize线程数限制.

    //返回值总结:
    //true 表示创建worker成功,且线程启动

    //false 表示创建失败。
    //1.线程池状态rs > SHUTDOWN (STOP/TIDYING/TERMINATION)
    //2.rs == SHUTDOWN 但是队列中已经没有任务了 或者 当前状态是SHUTDOWN且队列未空,但是firstTask不为null
    //3.当前线程池已经达到指定指标(coprePoolSize 或者 maximumPoolSIze)
    //4.threadFactory 创建的线程是null
    private boolean addWorker(Runnable firstTask, boolean core) {
        //自旋 判断当前线程池状态是否允许创建线程的事情。
        retry:
        for (;;) {
            //获取当前ctl值保存到c
            int c = ctl.get();
            //获取当前线程池运行状态 保存到rs长
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.

            //条件一:rs >= SHUTDOWN 成立:说明当前线程池状态不是running状态
            //条件二:前置条件,当前的线程池状态不是running状态  ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())
            //rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty()
            //表示:当前线程池状态是SHUTDOWN状态 & 提交的任务是空,addWorker这个方法可能不是execute调用的。 & 当前任务队列不是空
            //排除掉这种情况,当前线程池是SHUTDOWN状态,但是队列里面还有任务尚未处理完,这个时候是允许添加worker,但是不允许再次提交task。
            if (rs >= SHUTDOWN &&
                    ! (rs == SHUTDOWN &&
                            firstTask == null &&
                            ! workQueue.isEmpty()))
                //什么情况下回返回false?
                //线程池状态 rs > SHUTDOWN
                //rs == SHUTDOWN 但是队列中已经没有任务了 或者 rs == SHUTDOWN 且 firstTask != null
                return false;

            //上面这些代码,就是判断 当前线程池状态 是否允许添加线程。


            //内部自旋 获取创建线程令牌的过程。
            for (;;) {
                //获取当前线程池中线程数量 保存到wc中
                int wc = workerCountOf(c);

                //条件一:wc >= CAPACITY 永远不成立,因为CAPACITY是一个5亿多大的数字
                //条件二:wc >= (core ? corePoolSize : maximumPoolSize)
                //core == true ,判断当前线程数量是否>=corePoolSize,会拿核心线程数量做限制。
                //core == false,判断当前线程数量是否>=maximumPoolSize,会拿最大线程数量做限制。
                if (wc >= CAPACITY ||
                        wc >= (core ? corePoolSize : maximumPoolSize))
                    //执行到这里,说明当前无法添加线程了,已经达到指定限制了
                    return false;

                //条件成立:说明记录线程数量已经加1成功,相当于申请到了一块令牌。
                //条件失败:说明可能有其它线程,修改过ctl这个值了。
                //可能发生过什么事?
                //1.其它线程execute() 申请过令牌了,在这之前。导致CAS失败
                //2.外部线程可能调用过 shutdown() 或者 shutdownNow() 导致线程池状态发生变化了,咱们知道 ctl 高3位表示状态
                //状态改变后,cas也会失败。
                if (compareAndIncrementWorkerCount(c))
                    //进入到这里面,一定是cas成功啦!申请到令牌了
                    //直接跳出了 retry 外部这个for自旋。
                    break retry;

                //CAS失败,没有成功的申请到令牌
                //获取最新的ctl值
                c = ctl.get();  // Re-read ctl
                //判断当前线程池状态是否发生过变化,如果外部在这之前调用过shutdown. shutdownNow 会导致状态变化。
                if (runStateOf(c) != rs)
                    //状态发生变化后,直接返回到外层循环,外层循环负责判断当前线程池状态,是否允许创建线程。
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        //表示创建的worker是否已经启动,false未启动  true启动
        boolean workerStarted = false;
        //表示创建的worker是否添加到池子中了 默认false 未添加 true是添加。
        boolean workerAdded = false;

        //w表示后面创建worker的一个引用。
        Worker w = null;
        try {
            //创建Worker,执行完后,线程应该是已经创建好了。
            w = new Worker(firstTask);

            //将新创建的worker节点的线程 赋值给 t
            final Thread t = w.thread;

            //为什么要做 t != null 这个判断?
            //为了防止ThreadFactory 实现类有bug,因为ThreadFactory 是一个接口,谁都可以实现。
            //万一哪个 小哥哥 脑子一热,有bug,创建出来的线程 是null、、
            //Doug lea考虑的比较全面。肯定会防止他自己的程序报空指针,所以这里一定要做!
            if (t != null) {
                //将全局锁的引用保存到mainLock
                final ReentrantLock mainLock = this.mainLock;
                //持有全局锁,可能会阻塞,直到获取成功为止,同一时刻 操纵 线程池内部相关的操作,都必须持锁。
                mainLock.lock();
                //从这里加锁之后,其它线程 是无法修改当前线程池状态的。
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    //获取最新线程池运行状态保存到rs中
                    int rs = runStateOf(ctl.get());

                    //条件一:rs < SHUTDOWN 成立:最正常状态,当前线程池为RUNNING状态.
                    //条件二:前置条件:当前线程池状态不是RUNNING状态。
                    //(rs == SHUTDOWN && firstTask == null)  当前状态为SHUTDOWN状态且firstTask为空。其实判断的就是SHUTDOWN状态下的特殊情况,
                    //只不过这里不再判断队列是否为空了
                    if (rs < SHUTDOWN ||
                            (rs == SHUTDOWN && firstTask == null)) {
                        //t.isAlive() 当线程start后,线程isAlive会返回true。
                        //防止脑子发热的程序员,ThreadFactory创建线程返回给外部之前,将线程start了。。
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();

                        //将咱们创建的worker添加到线程池中。
                        workers.add(w);
                        //获取最新当前线程池线程数量
                        int s = workers.size();
                        //条件成立:说明当前线程数量是一个新高。更新largestPoolSize
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        //表示线程已经追加进线程池中了。
                        workerAdded = true;
                    }
                } finally {
                    //释放线程池全局锁。
                    mainLock.unlock();
                }
                //条件成立:说明 添加worker成功
                //条件失败:说明线程池在lock之前,线程池状态发生了变化,导致添加失败。
                if (workerAdded) {
                    //成功后,则将创建的worker启动,线程启动。
                    t.start();
                    //启动标记设置为true
                    workerStarted = true;
                }
            }

        } finally {
            //条件成立:! workerStarted 说明启动失败,需要做清理工作。
            if (! workerStarted)
                //失败时做什么清理工作?
                //1.释放令牌
                //2.将当前worker清理出workers集合
                addWorkerFailed(w);
        }

        //返回新创建的线程是否启动。
        return workerStarted;
    }

    /**
     * Rolls back the worker thread creation.
     * - removes worker from workers, if present
     * - decrements worker count
     * - rechecks for termination, in case the existence of this
     *   worker was holding up termination
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        //持有线程池全局锁,因为操作的是线程池相关的东西。
        mainLock.lock();
        try {
            //条件成立:需要将worker在workers中清理出去。
            if (w != null)
                workers.remove(w);
            //将线程池计数恢复-1,前面+1过,这里因为失败,所以要-1,相当于归还令牌。
            decrementWorkerCount();
            //回头讲,shutdown shutdownNow再说。
            tryTerminate();
        } finally {
            //释放线程池全局锁。
            mainLock.unlock();
        }

    }


    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        //条件成立:代表当前w 这个worker是发生异常退出的,task任务执行过程中向上抛出异常了..
        //异常退出时,ctl计数,并没有-1
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        //获取线程池的全局锁引用
        final ReentrantLock mainLock = this.mainLock;
        //加锁
        mainLock.lock();
        try {
            //将当前worker完成的task数量,汇总到线程池的completedTaskCount
            completedTaskCount += w.completedTasks;
            //将worker从池子中移除..
            workers.remove(w);
        } finally {
            //释放全局锁
            mainLock.unlock();
        }


        tryTerminate();

        //获取最新ctl值
        int c = ctl.get();
        //条件成立:当前线程池状态为 RUNNING 或者 SHUTDOWN状态
        if (runStateLessThan(c, STOP)) {

            //条件成立:当前线程是正常退出..
            if (!completedAbruptly) {

                //min表示线程池最低持有的线程数量
                //allowCoreThreadTimeOut == true => 说明核心线程数内的线程,也会超时被回收。 min == 0
                //allowCoreThreadTimeOut == false => min == corePoolSize
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;


                //线程池状态:RUNNING SHUTDOWN
                //条件一:假设min == 0 成立
                //条件二:! workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;

                //条件成立:线程池中还拥有足够的线程。
                //考虑一个问题: workerCountOf(c) >= min  =>  (0 >= 0) ?
                //有可能!
                //什么情况下? 当线程池中的核心线程数是可以被回收的情况下,会出现这种情况,这种情况下,当前线程池中的线程数 会变为0
                //下次再提交任务时,会再创建线程。
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }

            //1.当前线程在执行task时 发生异常,这里一定要创建一个新worker顶上去。
            //2.!workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。 当前状态为 RUNNING || SHUTDOWN
            //3.当前线程数量 < corePoolSize值,此时会创建线程,维护线程池数量在corePoolSize个。
            addWorker(null, false);
        }
    }


    //什么情况下会返回null?
    //1.rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
    //2.前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()
    //3.线程池中的线程数量 超过 最大限制时,会有一部分线程返回Null
    //4.线程池中的线程数超过corePoolSize时,会有一部分线程 超时后,返回null。
    private Runnable getTask() {
        //表示当前线程获取任务是否超时 默认false true表示已超时
        boolean timedOut = false; // Did the last poll() time out?

        //自旋
        for (;;) {
            //获取最新ctl值保存到c中。
            int c = ctl.get();
            //获取线程池当前运行状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //条件一:rs >= SHUTDOWN 条件成立:说明当前线程池是非RUNNING状态,可能是 SHUTDOWN/STOP....
            //条件二:(rs >= STOP || workQueue.isEmpty())
            //2.1:rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
            //2.2:前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()条件成立:说明当前线程池状态为SHUTDOWN状态 且 任务队列已空,此时一定返回null。
            //返回null,runWorker方法就会将返回Null的线程执行线程退出线程池的逻辑。
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                //使用CAS+死循环的方式让 ctl值 -1
                decrementWorkerCount();
                return null;
            }

            //执行到这里,有几种情况?
            //1.线程池是RUNNING状态
            //2.线程池是SHUTDOWN状态 但是队列还未空,此时可以创建线程。

            //获取线程池中的线程数量
            int wc = workerCountOf(c);

            // Are workers subject to culling?
            //timed == true 表示当前这个线程 获取 task 时 是支持超时机制的,使用queue.poll(xxx,xxx); 当获取task超时的情况下,下一次自旋就可能返回null了。
            //timed == false 表示当前这个线程 获取 task 时 是不支持超时机制的,当前线程会使用 queue.take();

            //情况1:allowCoreThreadTimeOut == true 表示核心线程数量内的线程 也可以被回收。
            //所有线程 都是使用queue.poll(xxx,xxx) 超时机制这种方式获取task.
            //情况2:allowCoreThreadTimeOut == false 表示当前线程池会维护核心数量内的线程。
            //wc > corePoolSize
            //条件成立:当前线程池中的线程数量是大于核心线程数的,此时让所有路过这里的线程,都是用poll 支持超时的方式去获取任务,
            //这样,就会可能有一部分线程获取不到任务,获取不到任务 返回Null,然后..runWorker会执行线程退出逻辑。
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;


            //条件一:(wc > maximumPoolSize || (timed && timedOut))
            //1.1:wc > maximumPoolSize  为什么会成立?setMaximumPoolSize()方法,可能外部线程将线程池最大线程数设置为比初始化时的要小
            //1.2: (timed && timedOut) 条件成立:前置条件,当前线程使用 poll方式获取task。上一次循环时  使用poll方式获取任务时,超时了
            //条件一 为true 表示 线程可以被回收,达到回收标准,当确实需要回收时再回收。

            //条件二:(wc > 1 || workQueue.isEmpty())
            //2.1: wc > 1  条件成立,说明当前线程池中还有其他线程,当前线程可以直接回收,返回null
            //2.2: workQueue.isEmpty() 前置条件 wc == 1, 条件成立:说明当前任务队列 已经空了,最后一个线程,也可以放心的退出。
            if ((wc > maximumPoolSize || (timed && timedOut))
                    && (wc > 1 || workQueue.isEmpty())) {
                //使用CAS机制 将 ctl值 -1 ,减1成功的线程,返回null
                //CAS成功的,返回Null
                //CAS失败? 为什么会CAS失败?
                //1.其它线程先你一步退出了
                //2.线程池状态发生变化了。
                if (compareAndDecrementWorkerCount(c))
                    return null;
                //再次自旋时,timed有可能就是false了,因为当前线程cas失败,很有可能是因为其它线程成功退出导致的,再次咨询时
                //检查发现,当前线程 就可能属于 不需要回收范围内了。
                continue;
            }




            try {
                //获取任务的逻辑


                Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();

                //条件成立:返回任务
                if (r != null)
                    return r;

                //说明当前线程超时了...
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

 
    //w 就是启动worker
    final void runWorker(Worker w) {
        //wt == w.thread
        Thread wt = Thread.currentThread();
        //将初始执行task赋值给task
        Runnable task = w.firstTask;
        //清空当前w.firstTask引用
        w.firstTask = null;
        //这里为什么先调用unlock? 就是为了初始化worker state == 0 和 exclusiveOwnerThread ==null
        w.unlock(); // allow interrupts

        //是否是突然退出,true->发生异常了,当前线程是突然退出,回头需要做一些处理
        //false->正常退出。
        boolean completedAbruptly = true;

        try {
            //条件一:task != null 指的就是firstTask是不是null,如果不是null,直接执行循环体里面。
            //条件二:(task = getTask()) != null   条件成立:说明当前线程在queue中获取任务成功,getTask这个方法是一个会阻塞线程的方法
            //getTask如果返回null,当前线程需要执行结束逻辑。
            while (task != null || (task = getTask()) != null) {
                //worker设置独占锁 为当前线程
                //为什么要设置独占锁呢?shutdown时会判断当前worker状态,根据独占锁是否空闲来判断当前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

                //条件一:runStateAtLeast(ctl.get(), STOP)  说明线程池目前处于STOP/TIDYING/TERMINATION 此时线程一定要给它一个中断信号
                //条件一成立:runStateAtLeast(ctl.get(), STOP)&& !wt.isInterrupted()
                //上面如果成立:说明当前线程池状态是>=STOP 且 当前线程是未设置中断状态的,此时需要进入到if里面,给当前线程一个中断。

                //假设:runStateAtLeast(ctl.get(), STOP) == false
                // (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP)) 在干吗呢?
                // Thread.interrupted() 获取当前中断状态,且设置中断位为false。连续调用两次,这个interrupted()方法 第二次一定是返回false.
                // runStateAtLeast(ctl.get(), STOP) 大概率这里还是false.
                // 其实它在强制刷新当前线程的中断标记位 false,因为有可能上一次执行task时,业务代码里面将当前线程的中断标记位 设置为了 true,且没有处理
                // 这里一定要强制刷新一下。不会再影响到后面的task了。
                //假设:Thread.interrupted() == true  且 runStateAtLeast(ctl.get(), STOP)) == true
                //这种情况有发生几率么?
                //有可能,因为外部线程在 第一次 (runStateAtLeast(ctl.get(), STOP) == false 后,有机会调用shutdown 、shutdownNow方法,将线程池状态修改
                //这个时候,也会将当前线程的中断标记位 再次设置回 中断状态。
                if ((runStateAtLeast(ctl.get(), STOP) ||
                        (Thread.interrupted() &&
                                runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                    wt.interrupt();


                try {
                    //钩子方法,留给子类实现的
                    beforeExecute(wt, task);
                    //表示异常情况,如果thrown不为空,表示 task运行过程中 向上层抛出异常了。
                    Throwable thrown = null;
                    try {
                        //task 可能是FutureTask 也可能是 普通的Runnable接口实现类。
                        //如果前面是通过submit()提交的 runnable/callable 会被封装成 FutureTask。这个不清楚,请看上一期,在b站。
                        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
                    task = null;
                    //更新worker完成任务数量
                    w.completedTasks++;

                    //worker处理完一个任务后,会释放掉独占锁
                    //1.正常情况下,会再次回到getTask()那里获取任务  while(getTask...)
                    //2.task.run()时内部抛出异常了..
                    w.unlock();
                }
            }

            //什么情况下,会来到这里?
            //getTask()方法返回null时,说明当前线程应该执行退出逻辑了。
            completedAbruptly = false;
        } finally {

            //task.run()内部抛出异常时,直接从 w.unlock() 那里 跳到这一行。
            //正常退出 completedAbruptly == false
            //异常退出 completedAbruptly == true
            processWorkerExit(w, completedAbruptly);
        }
    }

    // Public constructors and methods

    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) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                threadFactory, defaultHandler);
    }

  
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                Executors.defaultThreadFactory(), handler);
    }

  
    public ThreadPoolExecutor(int corePoolSize,//核心线程数限制
                              int maximumPoolSize,//最大线程限制
                              long keepAliveTime,//空闲线程存活时间
                              TimeUnit unit,//时间单位 seconds nano..
                              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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();

        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }


    //command 可以是普通的Runnable 实现类,也可以是 FutureTask
    public void execute(Runnable command) {
        //非空判断..
        if (command == null)
            throw new NullPointerException();
   
        //获取ctl最新值赋值给c,ctl :高3位 表示线程池状态,低位表示当前线程池线程数量。
        int c = ctl.get();
        //workerCountOf(c) 获取出当前线程数量
        //条件成立:表示当前线程数量小于核心线程数,此次提交任务,直接创建一个新的worker,对应线程池中多了一个新的线程。
        if (workerCountOf(c) < corePoolSize) {
            //addWorker 即为创建线程的过程,会创建worker对象,并且将command作为firstTask
            //core == true 表示采用核心线程数量限制  false表示采用 maximumPoolSize
            if (addWorker(command, true))
                //创建成功后,直接返回。addWorker方法里面会启动新创建的worker,将firstTask执行。
                return;

            //执行到这条语句,说明addWorker一定是失败了...
            //有几种可能呢??
            //1.存在并发现象,execute方法是可能有多个线程同时调用的,当workerCountOf(c) < corePoolSize成立后,
            //其它线程可能也成立了,并且向线程池中创建了worker。这个时候线程池中的核心线程数已经达到,所以...
            //2.当前线程池状态发生改变了。 RUNNING SHUTDOWN STOP TIDYING TERMINATION
            //当线程池状态是非RUNNING状态时,addWorker(firstTask!=null, true|false) 一定会失败。
            //SHUTDOWN 状态下,也有可能创建成功。前提 firstTask == null 而且当前 queue  不为空。特殊情况。
            c = ctl.get();
        }


        //执行到这里有几种情况?
        //1.当前线程数量已经达到corePoolSize
        //2.addWorker失败..

        //条件成立:说明当前线程池处于running状态,则尝试将 task 放入到workQueue中。
        if (isRunning(c) && workQueue.offer(command)) {
            //执行到这里,说明offer提交任务成功了..

            //再次获取ctl保存到recheck。
            int recheck = ctl.get();

            //条件一:! isRunning(recheck) 成立:说明你提交到队列之后,线程池状态被外部线程给修改 比如:shutdown() shutdownNow()
            //这种情况 需要把刚刚提交的任务删除掉。
            //条件二:remove(command) 有可能成功,也有可能失败
            //成功:提交之后,线程池中的线程还未消费(处理)
            //失败:提交之后,在shutdown() shutdownNow()之前,就被线程池中的线程 给处理。
            if (! isRunning(recheck) && remove(command))
                //提交之后线程池状态为 非running 且 任务出队成功,走个拒绝策略。
                reject(command);

            //有几种情况会到这里?
            //1.当前线程池是running状态(这个概率最大)
            //2.线程池状态是非running状态 但是remove提交的任务失败.

            //担心 当前线程池是running状态,但是线程池中的存活线程数量是0,这个时候,如果是0的话,会很尴尬,任务没线程去跑了,
            //这里其实是一个担保机制,保证线程池在running状态下,最起码得有一个线程在工作。
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }

        //执行到这里,有几种情况?
        //1.offer失败
        //2.当前线程池是非running状态

        //1.offer失败,需要做什么? 说明当前queue 满了!这个时候 如果当前线程数量尚未达到maximumPoolSize的话,会创建新的worker直接执行command
        //假设当前线程数量达到maximumPoolSize的话,这里也会失败,也走拒绝策略。

        //2.线程池状态为非running状态,这个时候因为 command != null addWorker 一定是返回false。
        else if (!addWorker(command, false))
            reject(command);

    }

    /**
     * Initiates an orderly shutdown in which previously submitted
     * tasks are executed, but no new tasks will be accepted.
     * Invocation has no additional effect if already shut down.
     *
     * <p>This method does not wait for previously submitted tasks to
     * complete execution.  Use {@link #awaitTermination awaitTermination}
     * to do that.
     *
     * @throws SecurityException {@inheritDoc}
     */
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        //获取线程池全局锁
        mainLock.lock();
        try {
            checkShutdownAccess();
            //设置线程池状态为SHUTDOWN
            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();
            //设置线程池状态为STOP
            advanceRunState(STOP);
            //中断线程池中所有线程
            interruptWorkers();
            //导出未处理的task
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }

        tryTerminate();
        //返回当前任务队列中 未处理的任务。
        return tasks;
    }

    public boolean isShutdown() {
        return ! isRunning(ctl.get());
    }

    /**
     * Returns true if this executor is in the process of terminating
     * after {@link #shutdown} or {@link #shutdownNow} but has not
     * completely terminated.  This method may be useful for
     * debugging. A return of {@code true} reported a sufficient
     * period after shutdown may indicate that submitted tasks have
     * ignored or suppressed interruption, causing this executor not
     * to properly terminate.
     *
     * @return {@code true} if terminating but not yet terminated
     */
    public boolean isTerminating() {
        int c = ctl.get();
        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
    }

    public boolean isTerminated() {
        return runStateAtLeast(ctl.get(), 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();
        }
    }

    /**
     * Invokes {@code shutdown} when this executor is no longer
     * referenced and it has no threads.
     */
    protected void finalize() {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null || acc == null) {
            shutdown();
        } else {
            PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
            AccessController.doPrivileged(pa, acc);
        }
    }

    /**
     * Sets the thread factory used to create new threads.
     *
     * @param threadFactory the new thread factory
     * @throws NullPointerException if threadFactory is null
     * @see #getThreadFactory
     */
    public void setThreadFactory(ThreadFactory threadFactory) {
        if (threadFactory == null)
            throw new NullPointerException();
        this.threadFactory = threadFactory;
    }

    /**
     * Returns the thread factory used to create new threads.
     *
     * @return the current thread factory
     * @see #setThreadFactory(ThreadFactory)
     */
    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }

    /**
     * Sets a new handler for unexecutable tasks.
     *
     * @param handler the new handler
     * @throws NullPointerException if handler is null
     * @see #getRejectedExecutionHandler
     */
    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        if (handler == null)
            throw new NullPointerException();
        this.handler = handler;
    }

    /**
     * Returns the current handler for unexecutable tasks.
     *
     * @return the current handler
     * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
     */
    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return handler;
    }

    /**
     * Sets the core number of threads.  This overrides any value set
     * in the constructor.  If the new value is smaller than the
     * current value, excess existing threads will be terminated when
     * they next become idle.  If larger, new threads will, if needed,
     * be started to execute any queued tasks.
     *
     * @param corePoolSize the new core size
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @see #getCorePoolSize
     */
    public void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0)
            throw new IllegalArgumentException();
        int delta = corePoolSize - this.corePoolSize;
        this.corePoolSize = corePoolSize;
        if (workerCountOf(ctl.get()) > corePoolSize)
            interruptIdleWorkers();
        else if (delta > 0) {
            // We don't really know how many new threads are "needed".
            // As a heuristic, prestart enough new workers (up to new
            // core size) to handle the current number of tasks in
            // queue, but stop if queue becomes empty while doing so.
            int k = Math.min(delta, workQueue.size());
            while (k-- > 0 && addWorker(null, true)) {
                if (workQueue.isEmpty())
                    break;
            }
        }
    }

    /**
     * Returns the core number of threads.
     *
     * @return the core number of threads
     * @see #setCorePoolSize
     */
    public int getCorePoolSize() {
        return corePoolSize;
    }

    /**
     * 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);
    }

    /**
     * Same as prestartCoreThread except arranges that at least one
     * thread is started even if corePoolSize is 0.
     */
    void ensurePrestart() {
        int wc = workerCountOf(ctl.get());
        if (wc < corePoolSize)
            addWorker(null, true);
        else if (wc == 0)
            addWorker(null, false);
    }

    /**
     * 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;
    }

    /**
     * Returns true if this pool allows core threads to time out and
     * terminate if no tasks arrive within the keepAlive time, being
     * replaced if needed when new tasks arrive. When true, the same
     * keep-alive policy applying to non-core threads applies also to
     * core threads. When false (the default), core threads are never
     * terminated due to lack of incoming tasks.
     *
     * @return {@code true} if core threads are allowed to time out,
     *         else {@code false}
     *
     * @since 1.6
     */
    public boolean allowsCoreThreadTimeOut() {
        return allowCoreThreadTimeOut;
    }


    public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                interruptIdleWorkers();
        }
    }

   
    public void setMaximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
            throw new IllegalArgumentException();
        this.maximumPoolSize = maximumPoolSize;
        if (workerCountOf(ctl.get()) > maximumPoolSize)
            interruptIdleWorkers();
    }

    /**
     * Returns the maximum allowed number of threads.
     *
     * @return the maximum allowed number of threads
     * @see #setMaximumPoolSize
     */
    public int getMaximumPoolSize() {
        return maximumPoolSize;
    }

  
    public void setKeepAliveTime(long time, TimeUnit unit) {
        if (time < 0)
            throw new IllegalArgumentException();
        if (time == 0 && allowsCoreThreadTimeOut())
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        long keepAliveTime = unit.toNanos(time);
        long delta = keepAliveTime - this.keepAliveTime;
        this.keepAliveTime = keepAliveTime;
        if (delta < 0)
            interruptIdleWorkers();
    }

    /**
     * Returns the thread keep-alive time, which is the amount of time
     * that threads in excess of the core pool size may remain
     * idle before being terminated.
     *
     * @param unit the desired time unit of the result
     * @return the time limit
     * @see #setKeepAliveTime(long, TimeUnit)
     */
    public long getKeepAliveTime(TimeUnit unit) {
        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
    }

    /* User-level queue utilities */

    /**
     * Returns the task queue used by this executor. Access to the
     * task queue is intended primarily for debugging and monitoring.
     * This queue may be in active use.  Retrieving the task queue
     * does not prevent queued tasks from executing.
     *
     * @return the task queue
     */
    public BlockingQueue<Runnable> getQueue() {
        return workQueue;
    }


    public boolean remove(Runnable task) {
        boolean removed = workQueue.remove(task);
        tryTerminate(); // In case SHUTDOWN and now empty
        return removed;
    }

    public void purge() {
        final BlockingQueue<Runnable> q = workQueue;
        try {
            Iterator<Runnable> it = q.iterator();
            while (it.hasNext()) {
                Runnable r = it.next();
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    it.remove();
            }
        } catch (ConcurrentModificationException fallThrough) {
            // Take slow path if we encounter interference during traversal.
            // Make copy for traversal and call remove for cancelled entries.
            // The slow path is more likely to be O(N*N).
            for (Object r : q.toArray())
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    q.remove(r);
        }

        tryTerminate(); // In case SHUTDOWN and now empty
    }

    /* Statistics */

    /**
     * Returns the current number of threads in the pool.
     *
     * @return the number of threads
     */
    public int getPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Remove rare and surprising possibility of
            // isTerminated() && getPoolSize() > 0
            return runStateAtLeast(ctl.get(), TIDYING) ? 0
                    : workers.size();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate number of threads that are actively
     * executing tasks.
     *
     * @return the number of threads
     */
    public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the largest number of threads that have ever
     * simultaneously been in the pool.
     *
     * @return the number of threads
     */
    public int getLargestPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            return largestPoolSize;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate total number of tasks that have ever been
     * scheduled for execution. Because the states of tasks and
     * threads may change dynamically during computation, the returned
     * value is only an approximation.
     *
     * @return the number of tasks
     */
    public long getTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers) {
                n += w.completedTasks;
                if (w.isLocked())
                    ++n;
            }
            return n + workQueue.size();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate total number of tasks that have
     * completed execution. Because the states of tasks and threads
     * may change dynamically during computation, the returned value
     * is only an approximation, but one that does not ever decrease
     * across successive calls.
     *
     * @return the number of tasks
     */
    public long getCompletedTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers)
                n += w.completedTasks;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns a string identifying this pool, as well as its state,
     * including indications of run state and estimated worker and
     * task counts.
     *
     * @return a string identifying this pool, as well as its state
     */
    public String toString() {
        long ncompleted;
        int nworkers, nactive;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            ncompleted = completedTaskCount;
            nactive = 0;
            nworkers = workers.size();
            for (Worker w : workers) {
                ncompleted += w.completedTasks;
                if (w.isLocked())
                    ++nactive;
            }
        } finally {
            mainLock.unlock();
        }
        int c = ctl.get();
        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
                (runStateAtLeast(c, TERMINATED) ? "Terminated" :
                        "Shutting down"));
        return super.toString() +
                "[" + rs +
                ", pool size = " + nworkers +
                ", active threads = " + nactive +
                ", queued tasks = " + workQueue.size() +
                ", completed tasks = " + ncompleted +
                "]";
    }

    /* Extension hooks */

    /**
     * Method invoked prior to executing the given Runnable in the
     * given thread.  This method is invoked by thread {@code t} that
     * will execute task {@code r}, and may be used to re-initialize
     * ThreadLocals, or to perform logging.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.beforeExecute} at the end of
     * this method.
     *
     * @param t the thread that will run task {@code r}
     * @param r the task that will be executed
     */
    protected void beforeExecute(Thread t, Runnable r) { }

  
    protected void afterExecute(Runnable r, Throwable t) { }

    /**
     * Method invoked when the Executor has terminated.  Default
     * implementation does nothing. Note: To properly nest multiple
     * overridings, subclasses should generally invoke
     * {@code super.terminated} within this method.
     */
    protected void terminated() { }

    /* Predefined RejectedExecutionHandlers */

    /**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                    " rejected from " +
                    e.toString());
        }
    }

    /**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容