0
// code exactly taken from java concurrency in practice

public class TimingThreadPool extends ThreadPoolExecutor {
  private final ThreadLocal<Long> startTime
    = new ThreadLocal<Long>();
  private final Logger log = Logger.getLogger("TimingThreadPool");
  private final AtomicLong numTasks = new AtomicLong();
  private final AtomicLong totalTime = new AtomicLong();

  protected void beforeExecute(Thread t, Runnable r) {
    super.beforeExecute(t, r);
    log.fine(String.format("Thread %s: start %s", t, r));
    startTime.set(System.nanoTime());
  }

  protected void afterExecute(Runnable r, Throwable t) {
    try {
    long endTime = System.nanoTime();
    long taskTime = endTime - startTime.get();
    numTasks.incrementAndGet();
    totalTime.addAndGet(taskTime);
    log.fine(String.format("Thread %s: end %s, time=%dns",
            t, r, taskTime));
    } finally {
    super.afterExecute(r, t);
    }
}

protected void terminated() {
try {
    log.info(String.format("Terminated: avg time=%dns",
            totalTime.get() / numTasks.get()));
    } finally {
    super.terminated();
    }
}
}

インスタンスはThreadPoolExecutorすべてのワーカー スレッドによって共有されます。はいの場合、メソッドbeforeExecute(...)afterExecute(...)同期すべきではありませんか? 答えが NO の場合、その理由は「ローカル変数がスレッド スタックに割り当てられ、numTasks、totalTime、startTime などの状態変数がスレッド限定/アトミックである」ことです。

4

1 に答える 1

0

beforeExecute と afterExecute を同期する必要はありません。これは、これら 2 つのメソッドで使用されるすべてのフィールドがスレッドセーフな java.util.logging.Logger (API から - Logger のすべてのメソッドはマルチスレッド セーフです)、または特別に設計された ThreadLocal および AtocmicLong であるためです。ロックフリーの使用。

ローカル変数に関しては、それらは 1 つのスレッドからのみアクセス可能であり、同期は必要ありません。

于 2013-02-01T12:19:45.290 に答える