ForkJoinWorkerThread.java revision 75a06e56a4cc4599946e21422513e4bafa759509
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 7package 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 * @hide 22 * @author Doug Lea 23 */ 24public class ForkJoinWorkerThread extends Thread { 25 /* 26 * ForkJoinWorkerThreads are managed by ForkJoinPools and perform 27 * ForkJoinTasks. For explanation, see the internal documentation 28 * of class ForkJoinPool. 29 * 30 * This class just maintains links to its pool and WorkQueue. The 31 * pool field is set immediately upon construction, but the 32 * workQueue field is not set until a call to registerWorker 33 * completes. This leads to a visibility race, that is tolerated 34 * by requiring that the workQueue field is only accessed by the 35 * owning thread. 36 */ 37 38 final ForkJoinPool pool; // the pool this thread works in 39 final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics 40 41 /** 42 * Creates a ForkJoinWorkerThread operating in the given pool. 43 * 44 * @param pool the pool this thread works in 45 * @throws NullPointerException if pool is null 46 */ 47 protected ForkJoinWorkerThread(ForkJoinPool pool) { 48 // Use a placeholder until a useful name can be set in registerWorker 49 super("aForkJoinWorkerThread"); 50 this.pool = pool; 51 this.workQueue = pool.registerWorker(this); 52 } 53 54 /** 55 * Returns the pool hosting this thread. 56 * 57 * @return the pool 58 */ 59 public ForkJoinPool getPool() { 60 return pool; 61 } 62 63 /** 64 * Returns the unique index number of this thread in its pool. 65 * The returned value ranges from zero to the maximum number of 66 * threads (minus one) that may exist in the pool, and does not 67 * change during the lifetime of the thread. This method may be 68 * useful for applications that track status or collect results 69 * per-worker-thread rather than per-task. 70 * 71 * @return the index number 72 */ 73 public int getPoolIndex() { 74 return workQueue.poolIndex >>> 1; // ignore odd/even tag bit 75 } 76 77 /** 78 * Initializes internal state after construction but before 79 * processing any tasks. If you override this method, you must 80 * invoke {@code super.onStart()} at the beginning of the method. 81 * Initialization requires care: Most fields must have legal 82 * default values, to ensure that attempted accesses from other 83 * threads work correctly even before this thread starts 84 * processing tasks. 85 */ 86 protected void onStart() { 87 } 88 89 /** 90 * Performs cleanup associated with termination of this worker 91 * thread. If you override this method, you must invoke 92 * {@code super.onTermination} at the end of the overridden method. 93 * 94 * @param exception the exception causing this thread to abort due 95 * to an unrecoverable error, or {@code null} if completed normally 96 */ 97 protected void onTermination(Throwable exception) { 98 } 99 100 /** 101 * This method is required to be public, but should never be 102 * called explicitly. It performs the main run loop to execute 103 * {@link ForkJoinTask}s. 104 */ 105 public void run() { 106 Throwable exception = null; 107 try { 108 onStart(); 109 pool.runWorker(workQueue); 110 } catch (Throwable ex) { 111 exception = ex; 112 } finally { 113 try { 114 onTermination(exception); 115 } catch (Throwable ex) { 116 if (exception == null) 117 exception = ex; 118 } finally { 119 pool.deregisterWorker(this, exception); 120 } 121 } 122 } 123} 124