--- jsr166/src/jsr166e/ForkJoinWorkerThread.java 2012/11/19 18:12:28 1.3 +++ jsr166/src/jsr166e/ForkJoinWorkerThread.java 2015/01/18 20:17:33 1.6 @@ -6,8 +6,6 @@ package jsr166e; -import java.util.concurrent.atomic.AtomicInteger; - /** * A thread managed by a {@link ForkJoinPool}, which executes * {@link ForkJoinTask}s. @@ -16,8 +14,8 @@ import java.util.concurrent.atomic.Atomi * scheduling or execution. However, you can override initialization * and termination methods surrounding the main task processing loop. * If you do create such a subclass, you will also need to supply a - * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it - * in a {@code ForkJoinPool}. + * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to + * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}. * * @since 1.7 * @author Doug Lea @@ -29,21 +27,15 @@ public class ForkJoinWorkerThread extend * of class ForkJoinPool. * * This class just maintains links to its pool and WorkQueue. The - * pool field is set upon construction, but the workQueue field is - * not set until the thread has started (unless forced early by a - * subclass constructor call to poolIndex()). This provides - * better memory placement (because this thread allocates queue - * and bookkeeping fields) but because the field is non-final, we - * require that it never be accessed except by the owning thread. + * pool field is set immediately upon construction, but the + * workQueue field is not set until a call to registerWorker + * completes. This leads to a visibility race, that is tolerated + * by requiring that the workQueue field is only accessed by the + * owning thread. */ final ForkJoinPool pool; // the pool this thread works in - ForkJoinPool.WorkQueue workQueue; // Work-stealing mechanics - - /** - * Sequence number for creating worker Names - */ - private static final AtomicInteger threadNumber = new AtomicInteger(); + final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics /** * Creates a ForkJoinWorkerThread operating in the given pool. @@ -52,12 +44,10 @@ public class ForkJoinWorkerThread extend * @throws NullPointerException if pool is null */ protected ForkJoinWorkerThread(ForkJoinPool pool) { - super(pool.workerNamePrefix.concat(Integer.toString(threadNumber.incrementAndGet()))); - setDaemon(true); + // Use a placeholder until a useful name can be set in registerWorker + super("aForkJoinWorkerThread"); this.pool = pool; - Thread.UncaughtExceptionHandler ueh = pool.ueh; - if (ueh != null) - setUncaughtExceptionHandler(ueh); + this.workQueue = pool.registerWorker(this); } /** @@ -70,22 +60,17 @@ public class ForkJoinWorkerThread extend } /** - * Returns the index number of this thread in its pool. The - * returned value ranges from zero to the maximum number of - * threads (minus one) that have ever been created in the pool. - * This method may be useful for applications that track status or - * collect results per-worker rather than per-task. + * Returns the unique index number of this thread in its pool. + * The returned value ranges from zero to the maximum number of + * threads (minus one) that may exist in the pool, and does not + * change during the lifetime of the thread. This method may be + * useful for applications that track status or collect results + * per-worker-thread rather than per-task. * * @return the index number */ public int getPoolIndex() { - // force early registration if called before started - ForkJoinPool.WorkQueue q; - if ((q = workQueue) == null) { - pool.registerWorker(this); - q = workQueue; - } - return q.poolIndex; + return workQueue.poolIndex >>> 1; // ignore odd/even tag bit } /** @@ -119,7 +104,6 @@ public class ForkJoinWorkerThread extend public void run() { Throwable exception = null; try { - pool.registerWorker(this); onStart(); pool.runWorker(workQueue); } catch (Throwable ex) {