スレッドプールのロックにだまされて、こんな風に使っていたのです.

2579 ワード

コンカレントライブラリをずっと使っていますが、ThreadPoolExecutorのソースコードは詳しく見たことがなく、主にDoug Lea大神のデザイン構想を見たいと思っています.
一つのコードについて質問ですが、主にWorkerというクラスで、内部にコードがあります.
private final ReentrantLock runLock = new ReentrantLock();
2つの方法があります
1つ目はrunTaskメソッドです
   private void runTask(Runnable task) {
            final ReentrantLock runLock = this.runLock;
            runLock.lock();
            try {
                /*
                 * Ensure that unless pool is stopping, this thread
                 * does not have its interrupt set. This requires a
                 * double-check of state in case the interrupt was
                 * cleared concurrently with a shutdownNow -- if so,
                 * the interrupt is re-enabled.
                 */
                if (runState < STOP &&
                    Thread.interrupted() &&
                    runState >= STOP)
                    thread.interrupt();
                /*
                 * Track execution state to ensure that afterExecute
                 * is called only if task completed or threw
                 * exception. Otherwise, the caught runtime exception
                 * will have been thrown by afterExecute itself, in
                 * which case we don't want to call it again.
                 */
                boolean ran = false;
                beforeExecute(thread, task);
                try {
                    task.run();
                    ran = true;
                    afterExecute(task, null);
                    ++completedTasks;
                } catch (RuntimeException ex) {
                    if (!ran)
                        afterExecute(task, ex);
                    throw ex;
                }
            } finally {
                runLock.unlock();
            }
        }

このWorkerは単なる例ではないので、つまり毎回新しいWorkerクラスが作成され、内部のロックもNEWの例です.このように鍵をかけるかどうかは区別がない.
私に理解させないで、見るまで
もう1つはinterruptIfIdleメソッドで、もともとこのように使われていたことが分かりました.
      void interruptIfIdle() {
            final ReentrantLock runLock = this.runLock;
            if (runLock.tryLock()) { 
                try {
                      if (thread != Thread.currentThread())
                           thread.interrupt();
                } finally {
                    runLock.unlock();
                }
            }
        }

ここのランロックtryLockは、ロックを取得した場合、現在のWorkerスレッドがRUNNING状態にないことを示し、スレッド割り込みを行うことができます.
ロックが取得されていない場合は、Workerがタスクを実行していることを示します.
この問題は主にコードを読むときに注意が足りないことであり,また経験主義は当然ロックが経験的範囲内の用法であると考えている.