package org.jivesoftware.util; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * A thread factory that allows threads to be named. * * An instance will either create new Threads, or use use a delegate Thread Factory. * When a new thread is generated, the name of the generated thread is replaced by concatenation of the provided thread * name prefix (which is an other argument of the constructor) and a sequence number. Sequence numbers are guaranteed to * be unique for threads generated by the same instance of this class. * * Optionally, this implementation allows the priority, isDaemon and threadGroup and stackSize value of the generated * threads to be set/overridden. Note that the threadGroup and stackSize value cannot be overridden when a delegate * thread factory is used. * * This implementation is thread safe when the provided delegate is thread safe. * * @author Guus der Kinderen, guus.der.kinderen@gmail.com */ public class NamedThreadFactory implements ThreadFactory { private final AtomicInteger threadNumber = new AtomicInteger(1); private final String threadNamePrefix; private final ThreadFactory delegate; private final Boolean daemon; private final Integer priority; private final Long stackSize; private final ThreadGroup threadGroup; /** * Constructs an instance that delegates thread creation to the thread factory passed as an argument. When the * delegate argument is null, the instance will instantiate threads itself (similar to the functionality of the * other constructor of this class). * * When null is provided for the optional arguments of this method, the values as defined by the delegate factory * are used. * * @param threadNamePrefix The prefix of the name for new threads (cannot be null or an empty string). * @param delegate The factory to which this implementation delegates to (null when no override is desired). * @param daemon override for the isDaemon value for new threads (null when no override is desired). * @param priority override for the priority value for new threads (null when no override is desired). */ public NamedThreadFactory( String threadNamePrefix, ThreadFactory delegate, Boolean daemon, Integer priority ) { if ( threadNamePrefix == null || threadNamePrefix.isEmpty() ) { throw new IllegalArgumentException( "Argument 'threadNamePrefix' cannot be null or an empty string." ); } this.threadNamePrefix = threadNamePrefix; this.delegate = delegate; this.daemon = daemon; this.priority = priority; this.threadGroup = null; this.stackSize = null; } /** * Constructs a thread factory that will create new Thread instances (as opposed to using a delegate thread * factory). * * When null is provided for the optional arguments of this method, default values as provided by the Thread class * implementation will be used. * * @param threadNamePrefix The prefix of the name for new threads (cannot be null or an empty string). * @param daemon the isDaemon value for new threads (null to use default value). * @param priority override for the priority value for new threads (null to use default value). * @param threadGroup override for the thread group (null to use default value). * @param stackSize override for the stackSize value for new threads (null to use default value). */ public NamedThreadFactory( String threadNamePrefix, Boolean daemon, Integer priority, ThreadGroup threadGroup, Long stackSize ) { if ( threadNamePrefix == null || threadNamePrefix.isEmpty() ) { throw new IllegalArgumentException( "Argument 'threadNamePrefix' cannot be null or an empty string." ); } this.delegate = null; this.threadNamePrefix = threadNamePrefix; this.daemon = daemon; this.priority = priority; this.threadGroup = threadGroup; this.stackSize = stackSize; } @Override public Thread newThread( Runnable runnable ) { final String name = threadNamePrefix + threadNumber.incrementAndGet(); final Thread thread; if ( delegate != null ) { thread = delegate.newThread( runnable ); thread.setName( name ); } else { if ( stackSize != null ) { thread = new Thread( threadGroup, runnable, name, stackSize ); } else { thread = new Thread( threadGroup, runnable, name ); } } if ( daemon != null && thread.isDaemon() != daemon ) { thread.setDaemon( daemon ); } if ( priority != null && thread.getPriority() != priority ) { thread.setPriority( priority ); } return thread; } }