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 023import org.apache.commons.lang3.Validate; 024 025/** 026 * <p> 027 * An implementation of the {@code ThreadFactory} interface that provides some 028 * configuration options for the threads it creates. 029 * </p> 030 * <p> 031 * A {@code ThreadFactory} is used for instance by an {@code ExecutorService} to 032 * create the threads it uses for executing tasks. In many cases users do not 033 * have to care about a {@code ThreadFactory} because the default one used by an 034 * {@code ExecutorService} will do. However, if there are special requirements 035 * for the threads, a custom {@code 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 {@code UncaughtExceptionHandler} for the thread. This handler is 060 * called if an uncaught exception occurs within the thread.</li> 061 * </ul> 062 * <p> 063 * {@code 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 {@code ThreadFactory} is 067 * used. 068 * </p> 069 * <p> 070 * Instances of {@code BasicThreadFactory} are not created directly, but the 071 * nested {@code 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 {@code BasicThreadFactory} is created and 074 * installed in an {@code 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 /** A counter for the threads created by this factory. */ 093 private final AtomicLong threadCounter; 094 095 /** Stores the wrapped factory. */ 096 private final ThreadFactory wrappedFactory; 097 098 /** Stores the uncaught exception handler. */ 099 private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler; 100 101 /** Stores the naming pattern for newly created threads. */ 102 private final String namingPattern; 103 104 /** Stores the priority. */ 105 private final Integer priority; 106 107 /** Stores the daemon status flag. */ 108 private final Boolean daemonFlag; 109 110 /** 111 * Creates a new instance of {@code ThreadFactoryImpl} and configures it 112 * from the specified {@code Builder} object. 113 * 114 * @param builder the {@code Builder} object 115 */ 116 private BasicThreadFactory(final Builder builder) { 117 if (builder.wrappedFactory == null) { 118 wrappedFactory = Executors.defaultThreadFactory(); 119 } else { 120 wrappedFactory = builder.wrappedFactory; 121 } 122 123 namingPattern = builder.namingPattern; 124 priority = builder.priority; 125 daemonFlag = builder.daemonFlag; 126 uncaughtExceptionHandler = builder.exceptionHandler; 127 128 threadCounter = new AtomicLong(); 129 } 130 131 /** 132 * Returns the wrapped {@code ThreadFactory}. This factory is used for 133 * actually creating threads. This method never returns <b>null</b>. If no 134 * {@code ThreadFactory} was passed when this object was created, a default 135 * thread factory is returned. 136 * 137 * @return the wrapped {@code ThreadFactory} 138 */ 139 public final ThreadFactory getWrappedFactory() { 140 return wrappedFactory; 141 } 142 143 /** 144 * Returns the naming pattern for naming newly created threads. Result can 145 * be <b>null</b> if no naming pattern was provided. 146 * 147 * @return the naming pattern 148 */ 149 public final String getNamingPattern() { 150 return namingPattern; 151 } 152 153 /** 154 * Returns the daemon flag. This flag determines whether newly created 155 * threads should be daemon threads. If <b>true</b>, this factory object 156 * calls {@code setDaemon(true)} on the newly created threads. Result can be 157 * <b>null</b> if no daemon flag was provided at creation time. 158 * 159 * @return the daemon flag 160 */ 161 public final Boolean getDaemonFlag() { 162 return daemonFlag; 163 } 164 165 /** 166 * Returns the priority of the threads created by this factory. Result can 167 * be <b>null</b> if no priority was specified. 168 * 169 * @return the priority for newly created threads 170 */ 171 public final Integer getPriority() { 172 return priority; 173 } 174 175 /** 176 * Returns the {@code UncaughtExceptionHandler} for the threads created by 177 * this factory. Result can be <b>null</b> if no handler was provided. 178 * 179 * @return the {@code UncaughtExceptionHandler} 180 */ 181 public final Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { 182 return uncaughtExceptionHandler; 183 } 184 185 /** 186 * Returns the number of threads this factory has already created. This 187 * class maintains an internal counter that is incremented each time the 188 * {@link #newThread(Runnable)} method is invoked. 189 * 190 * @return the number of threads created by this factory 191 */ 192 public long getThreadCount() { 193 return threadCounter.get(); 194 } 195 196 /** 197 * Creates a new thread. This implementation delegates to the wrapped 198 * factory for creating the thread. Then, on the newly created thread the 199 * corresponding configuration options are set. 200 * 201 * @param r the {@code Runnable} to be executed by the new thread 202 * @return the newly created thread 203 */ 204 @Override 205 public Thread newThread(final Runnable r) { 206 final Thread t = getWrappedFactory().newThread(r); 207 initializeThread(t); 208 209 return t; 210 } 211 212 /** 213 * Initializes the specified thread. This method is called by 214 * {@link #newThread(Runnable)} after a new thread has been obtained from 215 * the wrapped thread factory. It initializes the thread according to the 216 * options set for this factory. 217 * 218 * @param t the thread to be initialized 219 */ 220 private void initializeThread(final Thread t) { 221 222 if (getNamingPattern() != null) { 223 final Long count = Long.valueOf(threadCounter.incrementAndGet()); 224 t.setName(String.format(getNamingPattern(), count)); 225 } 226 227 if (getUncaughtExceptionHandler() != null) { 228 t.setUncaughtExceptionHandler(getUncaughtExceptionHandler()); 229 } 230 231 if (getPriority() != null) { 232 t.setPriority(getPriority().intValue()); 233 } 234 235 if (getDaemonFlag() != null) { 236 t.setDaemon(getDaemonFlag().booleanValue()); 237 } 238 } 239 240 /** 241 * <p> 242 * A <em>builder</em> class for creating instances of {@code 243 * BasicThreadFactory}. 244 * </p> 245 * <p> 246 * Using this builder class instances of {@code BasicThreadFactory} can be 247 * created and initialized. The class provides methods that correspond to 248 * the configuration options supported by {@code BasicThreadFactory}. Method 249 * chaining is supported. Refer to the documentation of {@code 250 * BasicThreadFactory} for a usage example. 251 * </p> 252 * 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 Validate.notNull(factory, "Wrapped ThreadFactory must not be null!"); 284 285 wrappedFactory = factory; 286 return this; 287 } 288 289 /** 290 * Sets the naming pattern to be used by the new {@code 291 * BasicThreadFactory}. 292 * 293 * @param pattern the naming pattern (must not be <b>null</b>) 294 * @return a reference to this {@code Builder} 295 * @throws NullPointerException if the naming pattern is <b>null</b> 296 */ 297 public Builder namingPattern(final String pattern) { 298 Validate.notNull(pattern, "Naming pattern must not be null!"); 299 300 namingPattern = pattern; 301 return this; 302 } 303 304 /** 305 * Sets the daemon flag for the new {@code BasicThreadFactory}. If this 306 * flag is set to <b>true</b> the new thread factory will create daemon 307 * threads. 308 * 309 * @param f the value of the daemon flag 310 * @return a reference to this {@code Builder} 311 */ 312 public Builder daemon(final boolean f) { 313 daemonFlag = Boolean.valueOf(f); 314 return this; 315 } 316 317 /** 318 * Sets the priority for the threads created by the new {@code 319 * BasicThreadFactory}. 320 * 321 * @param prio the priority 322 * @return a reference to this {@code Builder} 323 */ 324 public Builder priority(final int prio) { 325 priority = Integer.valueOf(prio); 326 return this; 327 } 328 329 /** 330 * Sets the uncaught exception handler for the threads created by the 331 * new {@code BasicThreadFactory}. 332 * 333 * @param handler the {@code UncaughtExceptionHandler} (must not be 334 * <b>null</b>) 335 * @return a reference to this {@code Builder} 336 * @throws NullPointerException if the exception handler is <b>null</b> 337 */ 338 public Builder uncaughtExceptionHandler( 339 final Thread.UncaughtExceptionHandler handler) { 340 Validate.notNull(handler, "Uncaught exception handler must not be null!"); 341 342 exceptionHandler = handler; 343 return this; 344 } 345 346 /** 347 * Resets this builder. All configuration options are set to default 348 * values. Note: If the {@link #build()} method was called, it is not 349 * necessary to call {@code reset()} explicitly because this is done 350 * automatically. 351 */ 352 public void reset() { 353 wrappedFactory = null; 354 exceptionHandler = null; 355 namingPattern = null; 356 priority = null; 357 daemonFlag = null; 358 } 359 360 /** 361 * Creates a new {@code BasicThreadFactory} with all configuration 362 * options that have been specified by calling methods on this builder. 363 * After creating the factory {@link #reset()} is called. 364 * 365 * @return the new {@code BasicThreadFactory} 366 */ 367 @Override 368 public BasicThreadFactory build() { 369 final BasicThreadFactory factory = new BasicThreadFactory(this); 370 reset(); 371 return factory; 372 } 373 } 374}