ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ForkJoinWorkerThread.java
Revision: 1.79
Committed: Fri Jan 17 18:12:07 2020 UTC (4 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.78: +34 -63 lines
Log Message:
FJ 1/20 refresh

File Contents

# Content
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 import java.security.AccessControlContext;
10 import java.security.AccessController;
11 import java.security.PrivilegedAction;
12 import java.security.ProtectionDomain;
13
14 /**
15 * A thread managed by a {@link ForkJoinPool}, which executes
16 * {@link ForkJoinTask}s.
17 * This class is subclassable solely for the sake of adding
18 * functionality -- there are no overridable methods dealing with
19 * scheduling or execution. However, you can override initialization
20 * and termination methods surrounding the main task processing loop.
21 * If you do create such a subclass, you will also need to supply a
22 * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
23 * {@linkplain ForkJoinPool#ForkJoinPool(int, ForkJoinWorkerThreadFactory,
24 * UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit)
25 * use it} in a {@code ForkJoinPool}.
26 *
27 * @since 1.7
28 * @author Doug Lea
29 */
30 public class ForkJoinWorkerThread extends Thread {
31 /*
32 * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
33 * ForkJoinTasks. For explanation, see the internal documentation
34 * of class ForkJoinPool.
35 *
36 * This class just maintains links to its pool and WorkQueue.
37 */
38
39 final ForkJoinPool pool; // the pool this thread works in
40 final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
41
42 /**
43 * Full nonpublic constructor.
44 */
45 ForkJoinWorkerThread(ThreadGroup group, ForkJoinPool pool,
46 boolean useSystemClassLoader, boolean isInnocuous) {
47 super(group, null, pool.nextWorkerThreadName(), 0L);
48 UncaughtExceptionHandler handler = (this.pool = pool).ueh;
49 this.workQueue = new ForkJoinPool.WorkQueue(this, isInnocuous);
50 super.setDaemon(true);
51 if (handler != null)
52 super.setUncaughtExceptionHandler(handler);
53 if (useSystemClassLoader)
54 super.setContextClassLoader(ClassLoader.getSystemClassLoader());
55 }
56
57 /**
58 * Creates a ForkJoinWorkerThread operating in the given thread group and
59 * pool.
60 *
61 * @param group if non-null, the thread group for this thread
62 * @param pool the pool this thread works in
63 * @throws NullPointerException if pool is null
64 */
65 protected ForkJoinWorkerThread(ThreadGroup group, ForkJoinPool pool) {
66 this(group, pool, false, false);
67 }
68
69 /**
70 * Creates a ForkJoinWorkerThread operating in the given pool.
71 *
72 * @param pool the pool this thread works in
73 * @throws NullPointerException if pool is null
74 */
75 protected ForkJoinWorkerThread(ForkJoinPool pool) {
76 this(null, pool, false, false);
77 }
78
79 /**
80 * Returns the pool hosting this thread.
81 *
82 * @return the pool
83 */
84 public ForkJoinPool getPool() {
85 return pool;
86 }
87
88 /**
89 * Returns the unique index number of this thread in its pool.
90 * The returned value ranges from zero to the maximum number of
91 * threads (minus one) that may exist in the pool, and does not
92 * change during the lifetime of the thread. This method may be
93 * useful for applications that track status or collect results
94 * per-worker-thread rather than per-task.
95 *
96 * @return the index number
97 */
98 public int getPoolIndex() {
99 return workQueue.getPoolIndex();
100 }
101
102 /**
103 * Initializes internal state after construction but before
104 * processing any tasks. If you override this method, you must
105 * invoke {@code super.onStart()} at the beginning of the method.
106 * Initialization requires care: Most fields must have legal
107 * default values, to ensure that attempted accesses from other
108 * threads work correctly even before this thread starts
109 * processing tasks.
110 */
111 protected void onStart() {
112 }
113
114 /**
115 * Performs cleanup associated with termination of this worker
116 * thread. If you override this method, you must invoke
117 * {@code super.onTermination} at the end of the overridden method.
118 *
119 * @param exception the exception causing this thread to abort due
120 * to an unrecoverable error, or {@code null} if completed normally
121 */
122 protected void onTermination(Throwable exception) {
123 }
124
125 /**
126 * This method is required to be public, but should never be
127 * called explicitly. It performs the main run loop to execute
128 * {@link ForkJoinTask}s.
129 */
130 public void run() {
131 Throwable exception = null;
132 ForkJoinPool p = pool;
133 ForkJoinPool.WorkQueue w = workQueue;
134 if (p != null && w != null) { // skip on failed initialization
135 try {
136 p.registerWorker(w);
137 onStart();
138 p.runWorker(w);
139 } catch (Throwable ex) {
140 exception = ex;
141 } finally {
142 try {
143 onTermination(exception);
144 } catch (Throwable ex) {
145 if (exception == null)
146 exception = ex;
147 } finally {
148 p.deregisterWorker(this, exception);
149 }
150 }
151 }
152 }
153
154 /**
155 * A worker thread that has no permissions, is not a member of any
156 * user-defined ThreadGroup, uses the system class loader as
157 * thread context class loader, and erases all ThreadLocals after
158 * running each top-level task.
159 */
160 static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
161 /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
162 private static final ThreadGroup innocuousThreadGroup =
163 AccessController.doPrivileged(new PrivilegedAction<>() {
164 public ThreadGroup run() {
165 ThreadGroup group = Thread.currentThread().getThreadGroup();
166 for (ThreadGroup p; (p = group.getParent()) != null; )
167 group = p;
168 return new ThreadGroup(
169 group, "InnocuousForkJoinWorkerThreadGroup");
170 }});
171
172 InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
173 super(innocuousThreadGroup, pool, true, true);
174 }
175
176 @Override // to silently fail
177 public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
178
179 @Override // paranoically
180 public void setContextClassLoader(ClassLoader cl) {
181 if (cl != null && ClassLoader.getSystemClassLoader() != cl)
182 throw new SecurityException("setContextClassLoader");
183 }
184 }
185 }