1

のソースコードをThreadPoolExecutor調べたところ、時間がkeepAliveTimeの設定値に達し、allowCoreThreadTimeOutがtrueになると、アイドル状態のすべてのワーカーに割り込みが発生することがわかりました。

runState> = SHUTDOWNの場合にのみ割り込みメソッドを呼び出すことができるのは、私には少し奇妙です。

以下のコードは、のメソッドからのものgetTask()ですThreadPoolExecutor

Runnable getTask() {
...
if (workerCanExit()) {
    if (runState >= SHUTDOWN) // Wake up others
        interruptIdleWorkers();
    return null;
   }
}

これは、runState> = SHUTDOWN(SHUTDOWN、STOP、またはTERMINATED)の場合にのみ、すべてのアイドルスレッドを中断できることを意味しますか?つまり、状態がRUNNINGのときに中断されることはありません。

4

3 に答える 3

2

あなたが正しいです。のこのgetTask() メソッドはThreadPoolExecutor、ワーカースレッドが実行する次のタスクを取得するために呼び出されます。このコードブロックは、メソッド呼び出しで実行可能な実行可能なタスクが識別されなかった場合にのみ実行されます。したがって、実行するものが見つからない場合は、シャットダウン状態をチェックする必要があります。

のJavadocからworkerCanExit()

タスクの取得に失敗したワーカースレッドが終了できるかどうかを確認します。プールが停止している場合、キューが空の場合、またはコアタイムアウトが許可されている場合でも、空でない可能性のあるキューを処理するスレッドが少なくとも1つある場合は、ワーカースレッドを停止できます。

于 2012-04-30T14:20:18.237 に答える
1

例として、ThreadPoolExecutorを次のように構成します:corePoolSize = 1、maxPoolSize = 5、workQueueSize = 1、keepAliveTime = 60s、allowCoreThreadTimeOut=false。

5つのタスク(各タスクには時間がかかります)を同時に提供すると、5つのタスクの1つがworkQueueに入り、他の4つのタスクはほぼ同時に新しく作成された4つのワーカースレッドによってすぐに処理されます。

このとき、ワーカースレッドの合計は4(workerThreadCount = 4)です。1つのスレッドがタスクを完了すると、ブロッキングメソッドworkQueue.take()またはworkQueue.poll(keepAliveTime)を呼び出してworkQueueを待機します。どのブロッキングメソッドが呼び出されるかは、workerThreadCountによって決定されます。

たとえば(仮説)、ある時点で、workerThread-0はtask-0を処理しています。task-1はworkQueueにとどまっています。workerThread-1はtask-2を処理しています。workerThread-2はtask-3を処理しています。workerThread-3はtask-4を処理しており、workerThreadCount==4です。

  1. workerThread-3はtask-4を完了し、今回は[workerThreadCount == 4]> [corePoolSize == 1]、workQueue.poll(keepAliveTime)によってworkQueueから次のtask(task-1)を取得します。次に、タスク1の処理に進みます。今回は、workerThreadCount==4です。ThreadPoolExecutor.javaのコードセグメントは次のとおりです。

    while (task != null || (task = getTask()) != null) { task.run(); } private Runnable getTask() { boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); }

  2. 次に、workerThread-0はtask-0を完了します。[workerThreadCount== 4]> [corePoolSize == 1]のため、workQueue.poll(keepAliveTime)によってworkQueueから次のタスクを取得します。ただし、今回はworkQueueが空であるため、workerThread-0はブロックされ、workerThread-0の状態はTIMED_WAITINGになります。keepAliveTimeが経過すると、workQueue.poll(keepAliveTime)はnullを返し、次に、workerThread-0がRunnable.run()から戻り、 TERMINATEDに変わります。今回はworkerThreadCount==3です。
  3. 次に、workerThread-1はtask-2を完了し、workerThread-0と同じ方法で戻ります。今回はworkerThreadCount==2です。
  4. 次に、workerThread-3はtask-1を完了し、workerThread-1と同じ方法で戻ります。今回はworkerThreadCount==1です。
  5. 次に、workerThread-2はtask-3を完了しますが、今回は[workerThreadCount ==1]が[corePoolSize==1]以下であるため、workQueue.take()によってworkQueueから次のタスクを取得するときに、 workQueueで使用可能なタスク。そして、その状態は待機中です。

注:ソースコードはJDK8からのものです。

于 2018-07-10T06:20:26.973 に答える
0

その通り。正しいタスク(中断が許可されている場合)は、中断されたフラグをチェックして終了する必要があります(つまり、run()から戻る)。

于 2012-04-30T14:14:10.367 に答える