ThreadPoolExecutorスレッドプール「ソースコード解析」

ThreadPoolExecutorスレッドプールのソースコード解析

白い歯は言います

長い時間がない、更新、学ぶべきではない理由はないが、完成学校はどのように書き込みを知らないだけでなく、耳で音の急増は、公開番号、同じトピックを見るために、公共よりも、人の書き込み数を公共の番号を飛ぶことを教えてくれました記事が多すぎる....... しかし、その後、私は同様の記事多くが、考え出したが、私はそれを自分自身を書いていない終える私たちは、そんなに良く、いくつかの助けをもたらすことができるだけであれば、関連する知識整理に役立ちます白い歯、またはそれ以上の出力を奨励する、唯一の収穫された出力強制入力は、私たちが知っている必要がありません

ThreadPoolExecutor类图

ThreadPoolExecutor类图

クラス図が示すことによって、ThreadPoolExecutorはExecutorServiceのであり、タスクは、スレッドプールによって行うことができます

共通のプロパティ

// 线程池中重要的变量 ctl,类型为 AtomicInteger,一个变量同时记录线程池状态和线程个数
// Integer 的位数为 32 位,其中高 3 位表示线程池的状态,低 29 位表示线程的个数。默认为 RUNNING 状态,线程个数为 0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 线程个数掩码位数,去掉高 3 位代表线程个数的 bit 位
private static final int COUNT_BITS = Integer.SIZE - 3;
// 线程最大个数,低 29 位 00011111111111111111111111111111
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
复制代码

JDKのソースコードを記述するので、ウェル状態の同時発現および以下の方法facieに関連付けられたスレッドプールスレッドの数によってCTL可変ビット操作をこれらの首長、変数の使用を賞賛しなければなりませんでした

一般的な方法

// 计算线程池的状态 ~CAPACITY 为:11100000000000000000000000000000,通过让 ctl 与 ~CAPACITY 相与,相当于取高 3 位的值(前面说了 ctl 高 3 位表示线程池状态)
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 计算线程个数 CAPACITY 为:00011111111111111111111111111111,通过让 ctl 与 CAPACITY 相与,相当于取低 29 位的值(前面说了 ctl 低 29 位表示线程个数)
private static int workerCountOf(int c)  { return c & CAPACITY; }
// 计算 ct l的值,用线程池状态和线程个数进行或运算
private static int ctlOf(int rs, int wc) { return rs | wc; }
复制代码

ソースコードでは、多くの場合、我々は、これらのメソッドは非常に巧妙な使用されていない参照してください?

プールのライフサイクルスレッド

// 默认状态,接收新任务并处理阻塞队列里的任务
private static final int RUNNING    = -1 << COUNT_BITS;
// 拒绝新任务但是处理阻塞队列里的任务
private static final int SHUTDOWN   =  0 << COUNT_BITS;
// 拒绝新任务并且抛弃阻塞队列里的任务,同时中断正在处理的任务
private static final int STOP       =  1 << COUNT_BITS;
// 所有任务都已经执行完成,线程数是 0,将调用 terminated() 方法
private static final int TIDYING    =  2 << COUNT_BITS;
// 终止状态,调用完 terminated() 方法后的状态
private static final int TERMINATED =  3 << COUNT_BITS;
复制代码

リマーク

あなたは上記の変数は、(i int型)Integer.toBinaryString方法により、バイナリ表現されているビューを表示する場合

スレッドプール変換の様子

RUNNING -> SHUTDOWN:当调用 shutdown() 方法时,也可能隐式的调用 finalize() 方法时(因为 finalize() 方法也是调用的 shutdown() 方法)
   On invocation of shutdown(), perhaps implicitly in finalize()
   
(RUNNING or SHUTDOWN) -> STOP:当调用 shutdownNow() 方法时
   On invocation of shutdownNow()
   
SHUTDOWN -> TIDYING:当队列和线程池都空时
   When both queue and pool are empty
   
STOP -> TIDYING:当线程池为空时
   When pool is empty
   
TIDYING -> TERMINATED:当 terminated() 方法完成时
   When the terminated() hook method has completed
复制代码

スレッドプールのコンストラクタ

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
复制代码

共通パラメータのようなスレッドプールを作成し、以下の簡単な紹介

corePoolSize:线程池中的核心线程数,即使他们处于空闲状态,除非 allowCoreThreadTimeOut 被设置了
maximumPoolSize:线程池中的最大线程数
workQueue:存放还未被执行任务的阻塞队列
threadFactory:创建线程的工厂类
rejectHandle:拒绝策略,当线程个数达到最大线程数,同时任务队列满了。就会执行拒绝策略。拒绝策略有:AbortPolicy(直接抛出异常)、CallerRunsPolicy(调用者所在线程来执行任务)、DiscardOldestPolicy(从任务队列中移除一个待执行的任务(最早提交的),然后再次执行任务)、DiscardPolicy(直接抛弃任务)      
keepAliveTime:存活时间,当线程个数大于了核心线程数,且处于空闲状态,这些空闲线程可存活的最大时间
复制代码

ソース・解体

方法を提出

スレッドプールを使用している場合、我々は通常ThreadPoolExecutor.submit(タスク)を直接スレッドプールへの方法、タスクを処理するために呼び出し、その後、未来の私達に戻って、メソッドの後ろにFuture.get()タスクの結果を得ることができます

public Future<?> submit(Runnable task) {
    // 任务为空,直接抛异常
    if (task == null) throw new NullPointerException();
    // 把任务封装成 RunnableFuture 
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    // 执行封装后的任务
    execute(ftask);
    return ftask;
}
复制代码
newTaskFor 方法

newTaskForタスクがクラスRunnableFutureにパッケージ化された結果は、メソッドを取得する取得することができ

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

public FutureTask(Runnable runnable, V result) {
    // 这里把 Runnable 适配成 Callable 类型的任务,result 是当任务成功完成时返回的结果,如果需要特殊结  果,就用 null 就行了
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    // 这里通过 RunnableAdapter 适配任务和任务的结果
    return new RunnableAdapter<T>(task, result);
}

// 适配类 RunnableAdapter,这种写法,我们可以借鉴下
static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    public T call() {
        task.run();
        return result;
    }
}
复制代码
メソッドを実行します

タスクは新しいものかもしれ実行するスレッドプールのスレッドにタスクを実行しようと、それは、スレッドプールを多重化することができます。スレッドプールは、タスクを実行できなかった場合(二つの理由があるかもしれない1スレッドプールが閉じられた、2スレッドが最大容量に達している)拒否ポリシーを実施します

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    /*
     * Proceed in 3 steps:留着原汁原味的总结
     *
     * 1. If fewer than corePoolSize threads are running, try to
     * start a new thread with the given command as its first
     * task.  The call to addWorker atomically checks runState and
     * workerCount, and so prevents false alarms that would add
     * threads when it shouldn't, by returning false.
     *
     * 2. If a task can be successfully queued, then we still need
     * to double-check whether we should have added a thread
     * (because existing ones died since last checking) or that
     * the pool shut down since entry into this method. So we
     * recheck state and if necessary roll back the enqueuing if
     * stopped, or start a new thread if there are none.
     *
     * 3. If we cannot queue task, then we try to add a new
     * thread.  If it fails, we know we are shut down or saturated
     * and so reject the task.
     */
    
    // 获取表示线程池状态和线程个数的组合变量 ctl
    int c = ctl.get();
    // 判断线程个数是否小于核心线程数,如果小于就新建一个核心线程来执行任务
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
   // 如果线程池处于 RUNNAING 状态,就把任务添加到阻塞队列中(代码运行到这里说明要么线程个数>=核心线程数,要么执行 addWorder 方法失败)
    if (isRunning(c) && workQueue.offer(command)) {
        // 再次获取组合变量 ctl,做二次检查(因为可能在此之前,线程池的状态已经发生了改变)
        int recheck = ctl.get();
        // 如果线程池状态不是 RNUUAING 状态,就把该任务从阻塞任务队列中移除,并执行拒绝策略
        if (! isRunning(recheck) && remove(command))
            reject(command);
        // 如果线程池中线程个数为 0,就新建一个线程
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    // 如果阻塞任务队列满了,新建线程,如果创建线程失败(即线程个数达到了最大线程个数),执行拒绝策略
    else if (!addWorker(command, false))
        reject(command);
}

复制代码
概要

ジョブが実行中のスレッドの数を決定し、スレッドプールに提出された場合、それは他のスレッドがアイドル状態であっても、このタスクを処理するために、以下の新しいスレッド以外であれば、corePoolSizeよりも少ないです。

無料のカーネルスレッドがある場合は、タスクを歩んで、直接タスクを実行します。コアスレッドがビジー状態の場合は、タスクキューに追加し、実行すべきタスクを置きます。

タスクキューがいっぱいになると、スレッドの数がより少ないmaximumPoolSizeよりも大きいcorePoolSizeを実行している場合は、タスクを実行するために、新しいスレッドを作成します。

addWorker 方法

最初の(スレッドまたはスレッドの最大数のコア数)を確認するかどうかの境界の現在の状態と、スレッドの数に応じて新しいワーカースレッドプールのスレッド。あなたは、新しい1つのワーカースレッドとブーツ、タスクかけてパスを作成することができる場合

/**
* 创建新的worker
*
* @param firstTask 提交给线程的任务,要最先执行,可以为 null
* @param core  如果为 true,表示以核心线程数为界创建线程  为 false 表示以最大线程数为界创建线程
* @return
*/
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        // 获取 ctl
        int c = ctl.get();
        // 获取线程池的状态
        int rs = runStateOf(c);

        // 这里的判断条件有点多,拆成 rs>=SHUTDOWN 和 !(rs == SHUTDOWN && firstTask == null &&!workQueue.isEmpty())
        // !(rs == SHUTDOWN && firstTask == null &&!workQueue.isEmpty()) 逆着考虑 ,如下:
        // rs!=SHUTDOWN 也就是为大于 shutdown,为 stop,tidying,terminated
        // firstTask != null
        // workQueue.isEmpty()
        // 如果线程池处于关闭状态,且满足下面条件之一的,不创建 worker
        //      线程池处于 stop,tidying,terminated 状态
        //      firstTask != null
        //      workQueue.isEmpty()
        // 注意:如果线程池处于 shutdown,且 firstTask 为 null,同时队列不为空,允许创建 worker
        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

        for (;;) {
            // 获取工作线程数
            int wc = workerCountOf(c);
            // 工作线程数大于最大容量或者工作线程数超过线程数的边界(根据 core 的值取不同的值) 时 不创建worker
            if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
            // 工作线程数 +1  通过 CAS
            // 这里如果失败,表示有并发操作
            if (compareAndIncrementWorkerCount(c))
                // 调出循环,执行真正的创建 worker 逻辑
                break retry;
            // 因为存在并发,需要再读取 ctl 值进行状态判断
            // Re-read ctl
            c = ctl.get();
            // 如果线程状态发生了变化,回到外部循环
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }

    // 校验已经都通过,开始创建 worker
    // 是否已经启动了 worker
    boolean workerStarted = false;
    // 是否已经添加了 worker
    boolean workerAdded = false;
    Worker w = null;
    try {
        // 把 task 封装成 worker,通过线程工厂创建线程,最后会把任务设置到 Thread 的 target 属性上,后续在执行线程的 start 方法时,就会执行对应的任务的 run 方法
        w = new Worker(firstTask);
        // 获取 worker 中的线程
        final Thread t = w.thread;
        if (t != null) {
            // 获取对象锁
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                // Recheck while holding lock.
                // Back out on ThreadFactory failure or if
                // shut down before lock acquired.
                int rs = runStateOf(ctl.get());

                // 如果线程池处于 Running 状态 或者 线程池处于 shutdown 状态且任务为 null(执行任务队列中的任务)
                if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                    // precheck that t is startable
                    // 检查线程是否为启动状态,如果为启动状态抛异常
                    if (t.isAlive())
                        throw new IllegalThreadStateException();
                    // 把新建的 worker 添加到 worker 集中
                    workers.add(w);
                    int s = workers.size();
                    // largestPoolSize 记录 workers 中个数存在过的最大值
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            // 新建的 worker 添加成功就启动线程,后续有分析
            if (workerAdded) {
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        // 线程没有启动成功,对上面创建线程的过程做回滚操作
        if (! workerStarted)
            // 回滚操作,比如把 worker 从 workers 中移除,把线程数减一
            addWorkerFailed(w);
    }
    return workerStarted;
}

复制代码
addWorkerFailed 方法

ロールバックワーカースレッドを作成する前に、

private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            // 从 workers 中移除 worker
            workers.remove(w);
        // 把线程数减一
        decrementWorkerCount();
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}

复制代码

addWorker方法をご紹介し、成功したスレッドのwokerセットに追加wokerが新たに作成された場合、論理スレッドがあり、スレッドは、メソッドが呼び出されるが開始されます、実際には、最終的には、労働者のrunメソッドに実行されます。スレッドファクトリによってWokerコンストラクタスレッドが作成されるため、次のように分析

Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    // 这里默认的线程工厂是 DefaultThreadFactory
    this.thread = getThreadFactory().newThread(this);
}

复制代码

スレッド、最後の呼び出しスレッドのコンストラクタ、スレッドによってスレッドファクトリを作成します(... Runnableをターゲット...)、ターゲットパラメータとしてスレッドを作成するために実行されるタスク、および、実行Thread.startのrunメソッドの後にメソッドを呼び出し、次に実行target.run、同様の薬剤

@Override
public void run() {
    if (target != null) {
        // 这个 target 就是创建线程时传递过来的那个任务
        target.run();
    }
}

复制代码

そして、あなたは私達がの労働者を実行する方法を実行することができ、実行する方法は、runWorkerメソッドを呼び出し、この方法での外観をできるようになります

runWorker方法

タスクキューからタスクを飲み続けると実行

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    // 把 status 设置为 0,允许中断
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        // 从任务队列中获取任务并执行
        while (task != null || (task = getTask()) != null) {
            // 这里加锁是为了避免任务运行期间,其他线程调用 shutdown 方法关闭线程池中正在执行任务的线程
            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

            // 如果线程池状态大于或等于 stop,即 runStateAtLeast(ctl.get(), STOP) 为 true,这个时候就要确保线程是中断的
            // 不用看||后面的条件,直接判断  !wt.isInterrupted(),因为线程池状态为暂停,要确保线程中断,如果没有中断,就要手动中断线程,即执行 wt.interrupt()
            // 如果线程池状态不是 stop,即 runStateAtLeast(ctl.get(), STOP) 为 false,就要确保线程没有中断,这样才能在后面执行任务
            // 这时候需要看 || 后面的 (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP)) ,因为要确保线程没有中断,调用Thread.interrupted()清除中断状态,
            // 这里需要再次进行验证线程池的状态,因为可能会有 shutdownNow 的情况
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                // 空方法体,子类可以实现,做一些特殊化处理工作
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 执行任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    // 空方法体,子类可以实现,做一些特殊化处理工作
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                // 统计当前 worker 完成了多少任务
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        // 执行清理工作
        processWorkerExit(w, completedAbruptly);
    }
}

复制代码

runWorker方法では、方法getTask、以下の簡単な存在であります

getTask方法
private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 满足下面两种情况任意一个就返回 null 同时把线程个数减 1
        // 1.线程池已经处于关闭状态
        // 2.线程池处于 shutdown,且队列为空
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);
        // 判断线程是否有时效性,前面说过,如果把 allowCoreThreadTimeOut 设为 false,那么核心线程数以内的线程是不会关闭的。如果设为 true 就只会存活 keepAliveTime 这么长时间
        // 如果线程数大于核心线程数的线程都有时效性
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        // 这个判断逻辑就是下面方法总结的第①点和第④点(这段代码我看了足足有半个小时,结合方法的注释终于弄明白了,感觉自己好笨)
        // 超时且超时的 worker 线程需要终止。
        // 如果任务队列非空,要保证当前 worker 线程不是线程池中最后一个线程(如果任务为空,当前线程是线程池中的最后一个线程也无妨,毕竟任务队列为空,当前 worker 线程关闭就关闭了,没影响)
        // 这里的判断条件可以看成 if (wc > maximumPoolSize || ((timed && timedOut) && (wc > 1 || workQueue.isEmpty()))
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            // 从队列中取任务,分为有超时限制和非超时限制两种情况
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            // 这里会抛出中断异常是因为可能会调用 setMaximumPoolSize 方法,把线程的最大数设置小了,那可能存在当前线程数大于新的最大线程数
            // 这样就得关闭多余的线程,所以重新进入 for 循环,并返回 null
            timedOut = false;
        }
    }
}

复制代码
概要getTask方法

タスク1.戻ります

2.リターンがnullの場合、この場合には、このような状況のために、次の4つの可能な理由、ワーカースレッドがあるため、スレッド数の減少を終了する必要があるということです

(方法setMaximumPoolSizeによって提供することができるように)①プール内のスレッドの数がスレッドの最大数よりも大きいです

②スレッドプールを閉じ、[タスクの両方が新しいタスクを拒否し、いないタスクキュー]

タスクキューが空の間、③スレッドプールは、シャットダウンである[]新しいタスクを拒否

終了する④残業して残業ワーカースレッド。タスクキューが空でない場合、現在のスレッドが最後のスレッドワーカースレッドプールは、タスクが空の場合、現在のスレッドが最後のスレッドプールのスレッドは、すべての後に、タスクキューが空で、とにかくである(ないことを確認するために、現在のワーカースレッドが閉じシャットダウン、)に影響を及ぼしませんでした

runWorkerクリーンアップ作業processWorkerExit方法は、以下の簡単な紹介を実行するための方法があります

processWorkerExit方法
private void processWorkerExit(Worker w, boolean completedAbruptly) {
    // 如果是突然完成,需要调整线程数
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 计算线程池完成的任务个数,并从 worke r线程集中删除当前 worker 线程
        completedTaskCount += w.completedTasks;
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }
    // 尝试把线程池的状态设置为 TERMINATED,该方法在后面分析
    tryTerminate();

    int c = ctl.get();
    // 线程池状态至少为 STOP
    if (runStateLessThan(c, STOP)) {
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        // 新建 worker 线程的条件为:当前线程数小于核心线程数或者任务队列不为空但没有运行的线程了(允许核心线程超时的情况下)
        addWorker(null, false);
    }
}

复制代码
tryTerminate 方法
final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        // 如果处于下面三种任意一种情况,就不能把线程池的状态设为 TERMINATED
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        // 代码执行到这里,说明有资格终止了。但是如果这个时候线程个数非 0,就中断一个空闲的线程来确保 shutdown 信号传播
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        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
    }
}

复制代码

あなたはここで、この記事のソースと一緒に慎重に見てみると、それは、右のスレッドプールの実装の原則のために少し感じすべきですか?最後に残り、スレッドプールは閉じている方法以下コンテンツ

シャットダウン方法
public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 权限校验
        checkShutdownAccess();
        // 设置线程池状态为 SHUTDOWN
        advanceRunState(SHUTDOWN);
        // 中断空闲线程
        interruptIdleWorkers();
        onShutdown(); // hook for ScheduledThreadPoolExecutor
    } finally {
        mainLock.unlock();
    }
    // 尝试设置线程池状态为 TERMINATED
    tryTerminate();
}

复制代码
shutdownNowの方法
public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 权限校验
        checkShutdownAccess();
        // 设置线程池状态为 STOP
        advanceRunState(STOP);
        // 中断所有线程
        interruptWorkers();
        // 将任务队列中的任务移动到 tasks 中
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    // 尝试设置线程池状态为 TERMINATED
    tryTerminate();
    return tasks;
}

复制代码

追伸

この記事は、毎日白い歯を指摘し、知識のスレッドプールの小片を整理する方法として、休日を書かもちろん、そこに多分問題、白い歯は、あなたが相続を批判することを願って、問題が公共の番号[日]メッセージを行くことが発見されました私はまた、我々は為替を議論する、[マイクロ] dingaiminIT文字を追加することができます。

推奨の歴史の記事

クラスローダ知識嘔吐仕上げ

最終面5は、適格な提供の評判になった後アリは、三辺、幸い適格補間場所に掛け

オリジナル| ES広告転置インデックスアーキテクチャの進化と最適化

広告アーキテクチャおよび最適化された逆索引

CPU使用率が高すぎて、あまりにもJVMの古い調査プロセスを占有しました

FGCは頻繁にそれが殺人者であることが判明しました

歳と100%が占められ、道でのバグVERTX-Redisのクライアントを発見しました

KafkaProducerソースコード解析

ネットワーク層のカフカサーバソースコード解析

Redisの有効期限ポリシーを実現する方法ですか?

オリジナル| HashMapのは、これら二つの点あれば、面接は問題ありません理解して

オリジナル|インタビュアー:Javaオブジェクトヒープに割り当てがしなければなりませんか?

オリジナル|この舗装の質問には、ほとんどの人はそれが間違ってました

同僚:「再試行」抽象アウトそれのようなツールであること

参考資料

  1. juejin.im/entry/59b23...
  2. 「Javaの非同期本当のプログラミングは、」世間の注目を歓迎[いいえ]漂白歯は、最新記事のために毎日、私たちは一緒に通信し、一緒に進行します!

おすすめ

転載: juejin.im/post/5e4602d66fb9a07c8a5a0d08