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