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