Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Written by Doug Lea with assistance from members of JCP JSR-166
      3  * Expert Group and released to the public domain, as explained at
      4  * http://creativecommons.org/publicdomain/zero/1.0/
      5  */
      6 
      7 package java.util.concurrent;
      8 
      9 /**
     10  * A thread managed by a {@link ForkJoinPool}, which executes
     11  * {@link ForkJoinTask}s.
     12  * This class is subclassable solely for the sake of adding
     13  * functionality -- there are no overridable methods dealing with
     14  * scheduling or execution.  However, you can override initialization
     15  * and termination methods surrounding the main task processing loop.
     16  * If you do create such a subclass, you will also need to supply a
     17  * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
     18  * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
     19  *
     20  * @since 1.7
     21  * @author Doug Lea
     22  */
     23 public class ForkJoinWorkerThread extends Thread {
     24     /*
     25      * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
     26      * ForkJoinTasks. For explanation, see the internal documentation
     27      * of class ForkJoinPool.
     28      *
     29      * This class just maintains links to its pool and WorkQueue.  The
     30      * pool field is set immediately upon construction, but the
     31      * workQueue field is not set until a call to registerWorker
     32      * completes. This leads to a visibility race, that is tolerated
     33      * by requiring that the workQueue field is only accessed by the
     34      * owning thread.
     35      */
     36 
     37     final ForkJoinPool pool;                // the pool this thread works in
     38     final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
     39 
     40     /**
     41      * Creates a ForkJoinWorkerThread operating in the given pool.
     42      *
     43      * @param pool the pool this thread works in
     44      * @throws NullPointerException if pool is null
     45      */
     46     protected ForkJoinWorkerThread(ForkJoinPool pool) {
     47         // Use a placeholder until a useful name can be set in registerWorker
     48         super("aForkJoinWorkerThread");
     49         this.pool = pool;
     50         this.workQueue = pool.registerWorker(this);
     51     }
     52 
     53     /**
     54      * Returns the pool hosting this thread.
     55      *
     56      * @return the pool
     57      */
     58     public ForkJoinPool getPool() {
     59         return pool;
     60     }
     61 
     62     /**
     63      * Returns the unique index number of this thread in its pool.
     64      * The returned value ranges from zero to the maximum number of
     65      * threads (minus one) that may exist in the pool, and does not
     66      * change during the lifetime of the thread.  This method may be
     67      * useful for applications that track status or collect results
     68      * per-worker-thread rather than per-task.
     69      *
     70      * @return the index number
     71      */
     72     public int getPoolIndex() {
     73         return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
     74     }
     75 
     76     /**
     77      * Initializes internal state after construction but before
     78      * processing any tasks. If you override this method, you must
     79      * invoke {@code super.onStart()} at the beginning of the method.
     80      * Initialization requires care: Most fields must have legal
     81      * default values, to ensure that attempted accesses from other
     82      * threads work correctly even before this thread starts
     83      * processing tasks.
     84      */
     85     protected void onStart() {
     86     }
     87 
     88     /**
     89      * Performs cleanup associated with termination of this worker
     90      * thread.  If you override this method, you must invoke
     91      * {@code super.onTermination} at the end of the overridden method.
     92      *
     93      * @param exception the exception causing this thread to abort due
     94      * to an unrecoverable error, or {@code null} if completed normally
     95      */
     96     protected void onTermination(Throwable exception) {
     97     }
     98 
     99     /**
    100      * This method is required to be public, but should never be
    101      * called explicitly. It performs the main run loop to execute
    102      * {@link ForkJoinTask}s.
    103      */
    104     public void run() {
    105         Throwable exception = null;
    106         try {
    107             onStart();
    108             pool.runWorker(workQueue);
    109         } catch (Throwable ex) {
    110             exception = ex;
    111         } finally {
    112             try {
    113                 onTermination(exception);
    114             } catch (Throwable ex) {
    115                 if (exception == null)
    116                     exception = ex;
    117             } finally {
    118                 pool.deregisterWorker(this, exception);
    119             }
    120         }
    121     }
    122 }
    123