001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3.concurrent; 018 019import java.lang.Thread.UncaughtExceptionHandler; 020import java.util.Objects; 021import java.util.concurrent.ExecutorService; 022import java.util.concurrent.Executors; 023import java.util.concurrent.ThreadFactory; 024import java.util.concurrent.atomic.AtomicLong; 025 026/** 027 * An implementation of the {@link ThreadFactory} interface that provides some 028 * configuration options for the threads it creates. 029 * <p> 030 * A {@link ThreadFactory} is used for instance by an {@link ExecutorService} to 031 * create the threads it uses for executing tasks. In many cases users do not 032 * have to care about a {@link ThreadFactory} because the default one used by an 033 * {@link ExecutorService} will do. However, if there are special requirements 034 * for the threads, a custom {@link ThreadFactory} has to be created. 035 * </p> 036 * <p> 037 * This class provides some frequently needed configuration options for the 038 * threads it creates. These are the following: 039 * </p> 040 * <ul> 041 * <li>A name pattern for the threads created by this factory can be specified. 042 * This is often useful if an application uses multiple executor services for 043 * different purposes. If the names of the threads used by these services have 044 * meaningful names, log output or exception traces can be much easier to read. 045 * Naming patterns are <em>format strings</em> as used by the {@code 046 * String.format()} method. The string can contain the place holder {@code %d} 047 * which will be replaced by the number of the current thread ({@code 048 * ThreadFactoryImpl} keeps a counter of the threads it has already created). 049 * For instance, the naming pattern {@code "My %d. worker thread"} will result 050 * in thread names like {@code "My 1. worker thread"}, {@code 051 * "My 2. worker thread"} and so on.</li> 052 * <li>A flag whether the threads created by this factory should be daemon 053 * threads. This can impact the exit behavior of the current Java application 054 * because the JVM shuts down if there are only daemon threads running.</li> 055 * <li>The priority of the thread. Here an integer value can be provided. The 056 * {@link Thread} class defines constants for valid ranges of priority 057 * values.</li> 058 * <li>The {@link UncaughtExceptionHandler} for the thread. This handler is 059 * called if an uncaught exception occurs within the thread.</li> 060 * </ul> 061 * <p> 062 * {@link BasicThreadFactory} wraps another thread factory which actually 063 * creates new threads. The configuration options are set on the threads created 064 * by the wrapped thread factory. On construction time the factory to be wrapped 065 * can be specified. If none is provided, a default {@link ThreadFactory} is 066 * used. 067 * </p> 068 * <p> 069 * Instances of {@link BasicThreadFactory} are not created directly, but the 070 * nested {@link Builder} class is used for this purpose. Using the builder only 071 * the configuration options an application is interested in need to be set. The 072 * following example shows how a {@link BasicThreadFactory} is created and 073 * installed in an {@link ExecutorService}: 074 * </p> 075 * 076 * <pre> 077 * // Create a factory that produces daemon threads with a naming pattern and 078 * // a priority 079 * BasicThreadFactory factory = new BasicThreadFactory.Builder() 080 * .namingPattern("workerthread-%d") 081 * .daemon(true) 082 * .priority(Thread.MAX_PRIORITY) 083 * .build(); 084 * // Create an executor service for single-threaded execution 085 * ExecutorService exec = Executors.newSingleThreadExecutor(factory); 086 * </pre> 087 * 088 * @since 3.0 089 */ 090public class BasicThreadFactory implements ThreadFactory { 091 092 /** 093 * A <em>builder</em> class for creating instances of {@code 094 * BasicThreadFactory}. 095 * <p> 096 * Using this builder class instances of {@link BasicThreadFactory} can be 097 * created and initialized. The class provides methods that correspond to 098 * the configuration options supported by {@link BasicThreadFactory}. Method 099 * 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}