1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang3.concurrent;
18
19 import java.lang.Thread.UncaughtExceptionHandler;
20 import java.util.Objects;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.ThreadFactory;
24 import java.util.concurrent.atomic.AtomicLong;
25
26 /**
27 * An implementation of the {@link ThreadFactory} interface that provides some
28 * configuration options for the threads it creates.
29 * <p>
30 * A {@link ThreadFactory} is used for instance by an {@link ExecutorService} to
31 * create the threads it uses for executing tasks. In many cases users do not
32 * have to care about a {@link ThreadFactory} because the default one used by an
33 * {@link ExecutorService} will do. However, if there are special requirements
34 * for the threads, a custom {@link ThreadFactory} has to be created.
35 * </p>
36 * <p>
37 * This class provides some frequently needed configuration options for the
38 * threads it creates. These are the following:
39 * </p>
40 * <ul>
41 * <li>A name pattern for the threads created by this factory can be specified.
42 * This is often useful if an application uses multiple executor services for
43 * different purposes. If the names of the threads used by these services have
44 * meaningful names, log output or exception traces can be much easier to read.
45 * Naming patterns are <em>format strings</em> as used by the {@code
46 * String.format()} method. The string can contain the place holder {@code %d}
47 * which will be replaced by the number of the current thread ({@code
48 * ThreadFactoryImpl} keeps a counter of the threads it has already created).
49 * For instance, the naming pattern {@code "My %d. worker thread"} will result
50 * in thread names like {@code "My 1. worker thread"}, {@code
51 * "My 2. worker thread"} and so on.</li>
52 * <li>A flag whether the threads created by this factory should be daemon
53 * threads. This can impact the exit behavior of the current Java application
54 * because the JVM shuts down if there are only daemon threads running.</li>
55 * <li>The priority of the thread. Here an integer value can be provided. The
56 * {@link Thread} class defines constants for valid ranges of priority
57 * values.</li>
58 * <li>The {@link UncaughtExceptionHandler} for the thread. This handler is
59 * called if an uncaught exception occurs within the thread.</li>
60 * </ul>
61 * <p>
62 * {@link BasicThreadFactory} wraps another thread factory which actually
63 * creates new threads. The configuration options are set on the threads created
64 * by the wrapped thread factory. On construction time the factory to be wrapped
65 * can be specified. If none is provided, a default {@link ThreadFactory} is
66 * used.
67 * </p>
68 * <p>
69 * Instances of {@link BasicThreadFactory} are not created directly, but the
70 * nested {@link Builder} class is used for this purpose. Using the builder only
71 * the configuration options an application is interested in need to be set. The
72 * following example shows how a {@link BasicThreadFactory} is created and
73 * installed in an {@link ExecutorService}:
74 * </p>
75 *
76 * <pre>
77 * // Create a factory that produces daemon threads with a naming pattern and
78 * // a priority
79 * BasicThreadFactory factory = new BasicThreadFactory.Builder()
80 * .namingPattern("workerthread-%d")
81 * .daemon(true)
82 * .priority(Thread.MAX_PRIORITY)
83 * .build();
84 * // Create an executor service for single-threaded execution
85 * ExecutorService exec = Executors.newSingleThreadExecutor(factory);
86 * </pre>
87 *
88 * @since 3.0
89 */
90 public class BasicThreadFactory implements ThreadFactory {
91
92 /**
93 * A <em>builder</em> class for creating instances of {@code
94 * BasicThreadFactory}.
95 * <p>
96 * Using this builder class instances of {@link BasicThreadFactory} can be
97 * created and initialized. The class provides methods that correspond to
98 * the configuration options supported by {@link BasicThreadFactory}. Method
99 * chaining is supported. Refer to the documentation of {@code
100 * BasicThreadFactory} for a usage example.
101 * </p>
102 */
103 public static class Builder implements org.apache.commons.lang3.builder.Builder<BasicThreadFactory> {
104
105 /** The wrapped factory. */
106 private ThreadFactory factory;
107
108 /** The uncaught exception handler. */
109 private Thread.UncaughtExceptionHandler exceptionHandler;
110
111 /**
112 * The naming pattern for newly created threads.
113 * <p>
114 * The naming pattern is a {@link String#format(String, Object...) format string} that expects a single argument. This argument is the number of the
115 * thread to be created. For instance, if the naming pattern is {@code "MyThread-%d"}, the first thread created by this factory will be named
116 * {@code "MyThread-1"}, the second one {@code "MyThread-2"} and so on.
117 * </p>
118 */
119 private String namingPattern;
120
121 /** The priority. */
122 private Integer priority;
123
124 /** The daemon flag. */
125 private Boolean daemon;
126
127 /**
128 * Constructs a new instance.
129 *
130 * @deprecated Use {@link BasicThreadFactory#builder()}.
131 */
132 @Deprecated
133 public Builder() {
134 // empty
135 }
136
137 /**
138 * Creates a new {@link BasicThreadFactory} with all configuration
139 * options that have been specified by calling methods on this builder.
140 * After creating the factory {@link #reset()} is called.
141 *
142 * @return The new {@link BasicThreadFactory}.
143 */
144 @Override
145 public BasicThreadFactory build() {
146 final BasicThreadFactory factory = new BasicThreadFactory(this);
147 reset();
148 return factory;
149 }
150
151 /**
152 * Sets the daemon flag for the new {@link BasicThreadFactory} to {@code true} causing a new thread factory to create daemon threads.
153 *
154 * @return A reference to this {@link Builder}.
155 * @since 3.18.0
156 */
157 public Builder daemon() {
158 return daemon(true);
159 }
160
161 /**
162 * Sets the daemon flag for the new {@link BasicThreadFactory}. If this
163 * flag is set to <strong>true</strong> the new thread factory will create daemon
164 * threads.
165 *
166 * @param daemon The value of the daemon flag.
167 * @return A reference to this {@link Builder}.
168 */
169 public Builder daemon(final boolean daemon) {
170 this.daemon = Boolean.valueOf(daemon);
171 return this;
172 }
173
174 /**
175 * Sets the naming pattern to be used by the new {@code
176 * BasicThreadFactory}.
177 * <p>
178 * The naming pattern is a {@link String#format(String, Object...) format string} that expects a single argument. This argument is the number of the
179 * thread to be created. For instance, if the naming pattern is {@code "MyThread-%d"}, the first thread created by this factory will be named
180 * {@code "MyThread-1"}, the second one {@code "MyThread-2"} and so on.
181 * </p>
182 *
183 * @param namingPattern The naming pattern (must not be {@code null}).
184 * @return A reference to this {@link Builder}.
185 * @throws NullPointerException Thrown if the naming pattern is {@code null}.
186 */
187 public Builder namingPattern(final String namingPattern) {
188 this.namingPattern = Objects.requireNonNull(namingPattern, "pattern");
189 return this;
190 }
191
192 /**
193 * Sets the priority for the threads created by the new {@code
194 * BasicThreadFactory}.
195 *
196 * @param priority The priority.
197 * @return A reference to this {@link Builder}.
198 */
199 public Builder priority(final int priority) {
200 this.priority = Integer.valueOf(priority);
201 return this;
202 }
203
204 /**
205 * Resets this builder. All configuration options are set to default
206 * values. Note: If the {@link #build()} method was called, it is not
207 * necessary to call {@code reset()} explicitly because this is done
208 * automatically.
209 */
210 public void reset() {
211 factory = null;
212 exceptionHandler = null;
213 namingPattern = null;
214 priority = null;
215 daemon = null;
216 }
217
218 /**
219 * Sets the uncaught exception handler for the threads created by the new {@link BasicThreadFactory}.
220 *
221 * @param exceptionHandler The {@link UncaughtExceptionHandler} (must not be {@code null}).
222 * @return A reference to this {@link Builder}.
223 * @throws NullPointerException Thrown if the exception handler is {@code null}.
224 */
225 public Builder uncaughtExceptionHandler(
226 final Thread.UncaughtExceptionHandler exceptionHandler) {
227 this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "handler");
228 return this;
229 }
230
231 /**
232 * Sets the {@link ThreadFactory} to be wrapped by the new {@code
233 * BasicThreadFactory}.
234 *
235 * @param factory The wrapped {@link ThreadFactory} (must not be {@code null})
236 * @return A reference to this {@link Builder}
237 * @throws NullPointerException Thrown if the passed in {@link ThreadFactory} is {@code null}.
238 */
239 public Builder wrappedFactory(final ThreadFactory factory) {
240 this.factory = Objects.requireNonNull(factory, "factory");
241 return this;
242 }
243 }
244
245 /**
246 * Creates a new builder.
247 *
248 * @return A new builder.
249 * @since 3.18.0
250 */
251 public static Builder builder() {
252 return new Builder();
253 }
254
255 /** A counter for the threads created by this factory. */
256 private final AtomicLong threadCounter;
257
258 /** The wrapped factory. */
259 private final ThreadFactory wrappedFactory;
260
261 /** The uncaught exception handler. */
262 private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
263
264 /**
265 * The naming pattern for newly created threads.
266 * <p>
267 * The naming pattern is a {@link String#format(String, Object...) format string} that expects a single argument. This argument is the number of the thread
268 * to be created. For instance, if the naming pattern is {@code "MyThread-%d"}, the first thread created by this factory will be named {@code "MyThread-1"},
269 * the second one {@code "MyThread-2"} and so on.
270 * </p>
271 */
272 private final String namingPattern;
273
274 /** Stores the priority. */
275 private final Integer priority;
276
277 /** Stores the daemon status flag. */
278 private final Boolean daemon;
279
280 /**
281 * Creates a new instance of {@link ThreadFactory} and configures it
282 * from the specified {@link Builder} object.
283 *
284 * @param builder The {@link Builder} object
285 */
286 private BasicThreadFactory(final Builder builder) {
287 wrappedFactory = builder.factory != null ? builder.factory : Executors.defaultThreadFactory();
288 namingPattern = builder.namingPattern;
289 priority = builder.priority;
290 daemon = builder.daemon;
291 uncaughtExceptionHandler = builder.exceptionHandler;
292 threadCounter = new AtomicLong();
293 }
294
295 /**
296 * Gets the daemon flag. This flag determines whether newly created
297 * threads should be daemon threads. If <strong>true</strong>, this factory object
298 * calls {@code setDaemon(true)} on the newly created threads. Result can be
299 * {@code null} if no daemon flag was provided at creation time.
300 *
301 * @return The daemon flag.
302 */
303 public final Boolean getDaemonFlag() {
304 return daemon;
305 }
306
307 /**
308 * Gets the naming pattern for naming newly created threads. Result can be {@code null} if no naming pattern was provided.
309 * <p>
310 * The naming pattern is a {@link String#format(String, Object...) format string} that expects a single argument. This argument is the number of the thread
311 * to be created. For instance, if the naming pattern is {@code "MyThread-%d"}, the first thread created by this factory will be named {@code "MyThread-1"},
312 * the second one {@code "MyThread-2"} and so on.
313 * </p>
314 *
315 * @return The naming pattern.
316 */
317 public final String getNamingPattern() {
318 return namingPattern;
319 }
320
321 /**
322 * Gets the priority of the threads created by this factory. Result can
323 * be {@code null} if no priority was specified.
324 *
325 * @return The priority for newly created threads.
326 */
327 public final Integer getPriority() {
328 return priority;
329 }
330
331 /**
332 * Gets the number of threads this factory has already created. This
333 * class maintains an internal counter that is incremented each time the
334 * {@link #newThread(Runnable)} method is invoked.
335 *
336 * @return The number of threads created by this factory.
337 */
338 public long getThreadCount() {
339 return threadCounter.get();
340 }
341
342 /**
343 * Gets the {@link UncaughtExceptionHandler} for the threads created by
344 * this factory. Result can be {@code null} if no handler was provided.
345 *
346 * @return The {@link UncaughtExceptionHandler}.
347 */
348 public final Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
349 return uncaughtExceptionHandler;
350 }
351
352 /**
353 * Gets the wrapped {@link ThreadFactory}. This factory is used for
354 * actually creating threads. This method never returns {@code null}. If no
355 * {@link ThreadFactory} was passed when this object was created, a default
356 * thread factory is returned.
357 *
358 * @return The wrapped {@link ThreadFactory}.
359 */
360 public final ThreadFactory getWrappedFactory() {
361 return wrappedFactory;
362 }
363
364 /**
365 * Initializes the specified thread. This method is called by
366 * {@link #newThread(Runnable)} after a new thread has been obtained from
367 * the wrapped thread factory. It initializes the thread according to the
368 * options set for this factory.
369 *
370 * @param thread The thread to be initialized.
371 */
372 private void initializeThread(final Thread thread) {
373 if (getNamingPattern() != null) {
374 final Long count = Long.valueOf(threadCounter.incrementAndGet());
375 thread.setName(String.format(getNamingPattern(), count));
376 }
377 if (getUncaughtExceptionHandler() != null) {
378 thread.setUncaughtExceptionHandler(getUncaughtExceptionHandler());
379 }
380 if (getPriority() != null) {
381 thread.setPriority(getPriority().intValue());
382 }
383 if (getDaemonFlag() != null) {
384 thread.setDaemon(getDaemonFlag().booleanValue());
385 }
386 }
387
388 /**
389 * Creates a new thread. This implementation delegates to the wrapped
390 * factory for creating the thread. Then, on the newly created thread the
391 * corresponding configuration options are set.
392 *
393 * @param runnable The {@link Runnable} to be executed by the new thread.
394 * @return The newly created thread.
395 */
396 @Override
397 public Thread newThread(final Runnable runnable) {
398 final Thread thread = getWrappedFactory().newThread(runnable);
399 initializeThread(thread);
400 return thread;
401 }
402 }