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 * http://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 * 030 * <p> 031 * A {@link ThreadFactory} is used for instance by an {@link ExecutorService} to 032 * create the threads it uses for executing tasks. In many cases users do not 033 * have to care about a {@link ThreadFactory} because the default one used by an 034 * {@link ExecutorService} will do. However, if there are special requirements 035 * for the threads, a custom {@link ThreadFactory} has to be created. 036 * </p> 037 * <p> 038 * This class provides some frequently needed configuration options for the 039 * threads it creates. These are the following: 040 * </p> 041 * <ul> 042 * <li>A name pattern for the threads created by this factory can be specified. 043 * This is often useful if an application uses multiple executor services for 044 * different purposes. If the names of the threads used by these services have 045 * meaningful names, log output or exception traces can be much easier to read. 046 * Naming patterns are <em>format strings</em> as used by the {@code 047 * String.format()} method. The string can contain the place holder {@code %d} 048 * which will be replaced by the number of the current thread ({@code 049 * ThreadFactoryImpl} keeps a counter of the threads it has already created). 050 * For instance, the naming pattern {@code "My %d. worker thread"} will result 051 * in thread names like {@code "My 1. worker thread"}, {@code 052 * "My 2. worker thread"} and so on.</li> 053 * <li>A flag whether the threads created by this factory should be daemon 054 * threads. This can impact the exit behavior of the current Java application 055 * because the JVM shuts down if there are only daemon threads running.</li> 056 * <li>The priority of the thread. Here an integer value can be provided. The 057 * {@code java.lang.Thread} class defines constants for valid ranges of priority 058 * values.</li> 059 * <li>The {@link UncaughtExceptionHandler} for the thread. This handler is 060 * called if an uncaught exception occurs within the thread.</li> 061 * </ul> 062 * <p> 063 * {@link BasicThreadFactory} wraps another thread factory which actually 064 * creates new threads. The configuration options are set on the threads created 065 * by the wrapped thread factory. On construction time the factory to be wrapped 066 * can be specified. If none is provided, a default {@link ThreadFactory} is 067 * used. 068 * </p> 069 * <p> 070 * Instances of {@link BasicThreadFactory} are not created directly, but the 071 * nested {@link Builder} class is used for this purpose. Using the builder only 072 * the configuration options an application is interested in need to be set. The 073 * following example shows how a {@link BasicThreadFactory} is created and 074 * installed in an {@link ExecutorService}: 075 * </p> 076 * 077 * <pre> 078 * // Create a factory that produces daemon threads with a naming pattern and 079 * // a priority 080 * BasicThreadFactory factory = new BasicThreadFactory.Builder() 081 * .namingPattern("workerthread-%d") 082 * .daemon(true) 083 * .priority(Thread.MAX_PRIORITY) 084 * .build(); 085 * // Create an executor service for single-threaded execution 086 * ExecutorService exec = Executors.newSingleThreadExecutor(factory); 087 * </pre> 088 * 089 * @since 3.0 090 */ 091public class BasicThreadFactory implements ThreadFactory { 092 /** 093 * A <em>builder</em> class for creating instances of {@code 094 * BasicThreadFactory}. 095 * 096 * <p> 097 * Using this builder class instances of {@link BasicThreadFactory} can be 098 * created and initialized. The class provides methods that correspond to 099 * the configuration options supported by {@link BasicThreadFactory}. Method 100 * chaining is supported. Refer to the documentation of {@code 101 * BasicThreadFactory} for a usage example. 102 * </p> 103 * 104 */ 105 public static class Builder 106 implements org.apache.commons.lang3.builder.Builder<BasicThreadFactory> { 107 108 /** The wrapped factory. */ 109 private ThreadFactory wrappedFactory; 110 111 /** The uncaught exception handler. */ 112 private Thread.UncaughtExceptionHandler exceptionHandler; 113 114 /** The naming pattern. */ 115 private String namingPattern; 116 117 /** The priority. */ 118 private Integer priority; 119 120 /** The daemon flag. */ 121 private Boolean daemon; 122 123 /** 124 * Creates a new {@link BasicThreadFactory} with all configuration 125 * options that have been specified by calling methods on this builder. 126 * After creating the factory {@link #reset()} is called. 127 * 128 * @return the new {@link BasicThreadFactory} 129 */ 130 @Override 131 public BasicThreadFactory build() { 132 final BasicThreadFactory factory = new BasicThreadFactory(this); 133 reset(); 134 return factory; 135 } 136 137 /** 138 * Sets the daemon flag for the new {@link BasicThreadFactory}. If this 139 * flag is set to <b>true</b> the new thread factory will create daemon 140 * threads. 141 * 142 * @param daemon the value of the daemon flag 143 * @return a reference to this {@link Builder} 144 */ 145 public Builder daemon(final boolean daemon) { 146 this.daemon = Boolean.valueOf(daemon); 147 return this; 148 } 149 150 /** 151 * Sets the naming pattern to be used by the new {@code 152 * BasicThreadFactory}. 153 * 154 * @param pattern the naming pattern (must not be <b>null</b>) 155 * @return a reference to this {@link Builder} 156 * @throws NullPointerException if the naming pattern is <b>null</b> 157 */ 158 public Builder namingPattern(final String pattern) { 159 Objects.requireNonNull(pattern, "pattern"); 160 161 namingPattern = pattern; 162 return this; 163 } 164 165 /** 166 * Sets the priority for the threads created by the new {@code 167 * BasicThreadFactory}. 168 * 169 * @param priority the priority 170 * @return a reference to this {@link Builder} 171 */ 172 public Builder priority(final int priority) { 173 this.priority = Integer.valueOf(priority); 174 return this; 175 } 176 177 /** 178 * Resets this builder. All configuration options are set to default 179 * values. Note: If the {@link #build()} method was called, it is not 180 * necessary to call {@code reset()} explicitly because this is done 181 * automatically. 182 */ 183 public void reset() { 184 wrappedFactory = null; 185 exceptionHandler = null; 186 namingPattern = null; 187 priority = null; 188 daemon = null; 189 } 190 191 /** 192 * Sets the uncaught exception handler for the threads created by the 193 * new {@link BasicThreadFactory}. 194 * 195 * @param handler the {@link UncaughtExceptionHandler} (must not be 196 * <b>null</b>) 197 * @return a reference to this {@link Builder} 198 * @throws NullPointerException if the exception handler is <b>null</b> 199 */ 200 public Builder uncaughtExceptionHandler( 201 final Thread.UncaughtExceptionHandler handler) { 202 Objects.requireNonNull(handler, "handler"); 203 204 exceptionHandler = handler; 205 return this; 206 } 207 208 /** 209 * Sets the {@link ThreadFactory} to be wrapped by the new {@code 210 * BasicThreadFactory}. 211 * 212 * @param factory the wrapped {@link ThreadFactory} (must not be 213 * <b>null</b>) 214 * @return a reference to this {@link Builder} 215 * @throws NullPointerException if the passed in {@link ThreadFactory} 216 * is <b>null</b> 217 */ 218 public Builder wrappedFactory(final ThreadFactory factory) { 219 Objects.requireNonNull(factory, "factory"); 220 221 wrappedFactory = factory; 222 return this; 223 } 224 } 225 226 /** A counter for the threads created by this factory. */ 227 private final AtomicLong threadCounter; 228 229 /** Stores the wrapped factory. */ 230 private final ThreadFactory wrappedFactory; 231 232 /** Stores the uncaught exception handler. */ 233 private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler; 234 235 /** Stores the naming pattern for newly created threads. */ 236 private final String namingPattern; 237 238 /** Stores the priority. */ 239 private final Integer priority; 240 241 /** Stores the daemon status flag. */ 242 private final Boolean daemon; 243 244 /** 245 * Creates a new instance of {@link ThreadFactory} and configures it 246 * from the specified {@link Builder} object. 247 * 248 * @param builder the {@link Builder} object 249 */ 250 private BasicThreadFactory(final Builder builder) { 251 if (builder.wrappedFactory == null) { 252 wrappedFactory = Executors.defaultThreadFactory(); 253 } else { 254 wrappedFactory = builder.wrappedFactory; 255 } 256 257 namingPattern = builder.namingPattern; 258 priority = builder.priority; 259 daemon = builder.daemon; 260 uncaughtExceptionHandler = builder.exceptionHandler; 261 262 threadCounter = new AtomicLong(); 263 } 264 265 /** 266 * Returns the daemon flag. This flag determines whether newly created 267 * threads should be daemon threads. If <b>true</b>, this factory object 268 * calls {@code setDaemon(true)} on the newly created threads. Result can be 269 * <b>null</b> if no daemon flag was provided at creation time. 270 * 271 * @return the daemon flag 272 */ 273 public final Boolean getDaemonFlag() { 274 return daemon; 275 } 276 277 /** 278 * Returns the naming pattern for naming newly created threads. Result can 279 * be <b>null</b> if no naming pattern was provided. 280 * 281 * @return the naming pattern 282 */ 283 public final String getNamingPattern() { 284 return namingPattern; 285 } 286 287 /** 288 * Returns the priority of the threads created by this factory. Result can 289 * be <b>null</b> if no priority was specified. 290 * 291 * @return the priority for newly created threads 292 */ 293 public final Integer getPriority() { 294 return priority; 295 } 296 297 /** 298 * Returns the number of threads this factory has already created. This 299 * class maintains an internal counter that is incremented each time the 300 * {@link #newThread(Runnable)} method is invoked. 301 * 302 * @return the number of threads created by this factory 303 */ 304 public long getThreadCount() { 305 return threadCounter.get(); 306 } 307 308 /** 309 * Returns the {@link UncaughtExceptionHandler} for the threads created by 310 * this factory. Result can be <b>null</b> if no handler was provided. 311 * 312 * @return the {@link UncaughtExceptionHandler} 313 */ 314 public final Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { 315 return uncaughtExceptionHandler; 316 } 317 318 /** 319 * Returns the wrapped {@link ThreadFactory}. This factory is used for 320 * actually creating threads. This method never returns <b>null</b>. If no 321 * {@link ThreadFactory} was passed when this object was created, a default 322 * thread factory is returned. 323 * 324 * @return the wrapped {@link ThreadFactory} 325 */ 326 public final ThreadFactory getWrappedFactory() { 327 return wrappedFactory; 328 } 329 330 /** 331 * Initializes the specified thread. This method is called by 332 * {@link #newThread(Runnable)} after a new thread has been obtained from 333 * the wrapped thread factory. It initializes the thread according to the 334 * options set for this factory. 335 * 336 * @param thread the thread to be initialized 337 */ 338 private void initializeThread(final Thread thread) { 339 340 if (getNamingPattern() != null) { 341 final Long count = Long.valueOf(threadCounter.incrementAndGet()); 342 thread.setName(String.format(getNamingPattern(), count)); 343 } 344 345 if (getUncaughtExceptionHandler() != null) { 346 thread.setUncaughtExceptionHandler(getUncaughtExceptionHandler()); 347 } 348 349 if (getPriority() != null) { 350 thread.setPriority(getPriority().intValue()); 351 } 352 353 if (getDaemonFlag() != null) { 354 thread.setDaemon(getDaemonFlag().booleanValue()); 355 } 356 } 357 358 /** 359 * Creates a new thread. This implementation delegates to the wrapped 360 * factory for creating the thread. Then, on the newly created thread the 361 * corresponding configuration options are set. 362 * 363 * @param runnable the {@link Runnable} to be executed by the new thread 364 * @return the newly created thread 365 */ 366 @Override 367 public Thread newThread(final Runnable runnable) { 368 final Thread thread = getWrappedFactory().newThread(runnable); 369 initializeThread(thread); 370 371 return thread; 372 } 373}