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