ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ForkJoinWorkerThread.java
Revision: 1.85
Committed: Fri May 6 16:03:05 2022 UTC (2 years ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.84: +10 -7 lines
Log Message:
sync with openjdk

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.AccessController;
10 import java.security.AccessControlContext;
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,
47 boolean clearThreadLocals) {
48 super(group, null, pool.nextWorkerThreadName(), 0L, !clearThreadLocals);
49 UncaughtExceptionHandler handler = (this.pool = pool).ueh;
50 this.workQueue = new ForkJoinPool.WorkQueue(this, 0);
51 if (clearThreadLocals)
52 workQueue.setClearThreadLocals();
53 super.setDaemon(true);
54 if (handler != null)
55 super.setUncaughtExceptionHandler(handler);
56 if (useSystemClassLoader)
57 super.setContextClassLoader(ClassLoader.getSystemClassLoader());
58 }
59
60 /**
61 * Creates a ForkJoinWorkerThread operating in the given thread group and
62 * pool, and with the given policy for preserving ThreadLocals.
63 *
64 * @param group if non-null, the thread group for this
65 * thread. Otherwise, the thread group is chosen by the security
66 * manager if present, else set to the current thread's thread
67 * group.
68 * @param pool the pool this thread works in
69 * @param preserveThreadLocals if true, always preserve the values of
70 * ThreadLocal variables across tasks; otherwise they may be cleared.
71 * @throws NullPointerException if pool is null
72 * @since 19
73 */
74 protected ForkJoinWorkerThread(ThreadGroup group, ForkJoinPool pool,
75 boolean preserveThreadLocals) {
76 this(group, pool, false, !preserveThreadLocals);
77 }
78
79 /**
80 * Creates a ForkJoinWorkerThread operating in the given pool.
81 *
82 * @param pool the pool this thread works in
83 * @throws NullPointerException if pool is null
84 */
85 protected ForkJoinWorkerThread(ForkJoinPool pool) {
86 this(null, pool, false, false);
87 }
88
89 /**
90 * Returns the pool hosting this thread.
91 *
92 * @return the pool
93 */
94 public ForkJoinPool getPool() {
95 return pool;
96 }
97
98 /**
99 * Returns the unique index number of this thread in its pool.
100 * The returned value ranges from zero to the maximum number of
101 * threads (minus one) that may exist in the pool, and does not
102 * change during the lifetime of the thread. This method may be
103 * useful for applications that track status or collect results
104 * per-worker-thread rather than per-task.
105 *
106 * @return the index number
107 */
108 public int getPoolIndex() {
109 return workQueue.getPoolIndex();
110 }
111
112 /**
113 * Initializes internal state after construction but before
114 * processing any tasks. If you override this method, you must
115 * invoke {@code super.onStart()} at the beginning of the method.
116 * Initialization requires care: Most fields must have legal
117 * default values, to ensure that attempted accesses from other
118 * threads work correctly even before this thread starts
119 * processing tasks.
120 */
121 protected void onStart() {
122 }
123
124 /**
125 * Performs cleanup associated with termination of this worker
126 * thread. If you override this method, you must invoke
127 * {@code super.onTermination} at the end of the overridden method.
128 *
129 * @param exception the exception causing this thread to abort due
130 * to an unrecoverable error, or {@code null} if completed normally
131 */
132 protected void onTermination(Throwable exception) {
133 }
134
135 /**
136 * This method is required to be public, but should never be
137 * called explicitly. It performs the main run loop to execute
138 * {@link ForkJoinTask}s.
139 */
140 public void run() {
141 Throwable exception = null;
142 ForkJoinPool p = pool;
143 ForkJoinPool.WorkQueue w = workQueue;
144 if (p != null && w != null) { // skip on failed initialization
145 try {
146 p.registerWorker(w);
147 onStart();
148 p.runWorker(w);
149 } catch (Throwable ex) {
150 exception = ex;
151 } finally {
152 try {
153 onTermination(exception);
154 } catch (Throwable ex) {
155 if (exception == null)
156 exception = ex;
157 } finally {
158 p.deregisterWorker(this, exception);
159 }
160 }
161 }
162 }
163
164 /**
165 * A worker thread that has no permissions, is not a member of any
166 * user-defined ThreadGroup, uses the system class loader as
167 * thread context class loader, and clears all ThreadLocals after
168 * running each top-level task.
169 */
170 static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
171 /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
172 private static final ThreadGroup innocuousThreadGroup;
173 @SuppressWarnings("removal")
174 private static final AccessControlContext innocuousACC;
175 InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
176 super(innocuousThreadGroup, pool, true, true);
177 }
178
179 @Override @SuppressWarnings("removal")
180 protected void onStart() {
181 Thread t = Thread.currentThread();
182 ThreadLocalRandom.setInheritedAccessControlContext(t, innocuousACC);
183 }
184
185 @Override // to silently fail
186 public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
187
188 @Override // paranoically
189 public void setContextClassLoader(ClassLoader cl) {
190 if (cl != null && ClassLoader.getSystemClassLoader() != cl)
191 throw new SecurityException("setContextClassLoader");
192 }
193
194 @SuppressWarnings("removal")
195 static AccessControlContext createACC() {
196 return new AccessControlContext(
197 new ProtectionDomain[] { new ProtectionDomain(null, null) });
198 }
199 static ThreadGroup createGroup() {
200 ThreadGroup group = Thread.currentThread().getThreadGroup();
201 for (ThreadGroup p; (p = group.getParent()) != null; )
202 group = p;
203 return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
204 }
205 static {
206 @SuppressWarnings("removal")
207 SecurityManager sm = System.getSecurityManager();
208 @SuppressWarnings("removal")
209 ThreadGroup g = innocuousThreadGroup =
210 (sm == null) ? createGroup() :
211 AccessController.doPrivileged(new PrivilegedAction<>() {
212 public ThreadGroup run() {
213 return createGroup(); }});
214 @SuppressWarnings("removal")
215 AccessControlContext a = innocuousACC =
216 (sm == null) ? createACC() :
217 AccessController.doPrivileged(new PrivilegedAction<>() {
218 public AccessControlContext run() {
219 return createACC(); }});
220 }
221 }
222 }