1, To set a more descriptive thread name. With the default ThreadFactory, it gives thread names in the form of pool-m-thread-n, such as pool-1-thread-1, pool-2-thread-1, pool-3-thread-1, etc. When these threads showing up in debugger, profiler, or monitoring tool, it's hard to know their purpose and how they were started.
2, To set thread daemon status. The default ThreadFactory produces non-daemon threads.
3, To set thread contextClassLoader to appropriate value. Threads created by the default ThreadFactory will inherit the contextClassLoader from the parent thread, which may not be what you want. In general, a pooled thread itself should not be associated with any specific class loader. Instead, the submitted task has the best knowledge about its class loading requirement, so the task
Runnable
or Callable
should manage the thread contextClassLoader for the duration of its run method.If the new thread does not need to access classes loaded in the parent thead, set its contextClassLoader to null. If a task needs visibility to a class loader, set its contextClassLoader at the beginning of its run method, and restore its contextClassLoader right before exiting run method.
The default ThreadFactory in JDK 6 java.util.concurrent is a package-private static nested class in
java.util.concurrent.Executors
:static class DefaultThreadFactory implements ThreadFactory {Note that poolNumber is declared as
static final AtomicInteger poolNumber = new AtomicInteger(1);
final ThreadGroup group;
final AtomicInteger threadNumber = new AtomicInteger(1);
final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null)? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
static final
and threadNumber as final
. Each instance of ThreadFactory is tied to a unique pool, and a static poolNumber tracks the sequence of all instances of DefaultThreadFactory. An instance of ThreadFactory (and the associated pool) contains multiple threads, and the instance field threadNumber tallies all threads therein.Both poolNumber and threadNumber fields are of type java.util.concurrent.AtomicInteger to take advantage of its atomic compound operations. Their initial value is 1 and getAndIncrement() is invoked to produce sequence like 1, 2, 3. Alternatively we could set its initial value to 0 and invoke incrementAndGet() to produce the same sequence.
Why poolNumber and threadNumber need to guard against concurrent access and modification? poolNumber is static and thus a shared data among all instances of DefaultThreadFactory. Multiple instances of
DefaultThreadFactory
may be incrementing it simutaneously, so it needs to be thread-safe.As for threadNumber, the creation of threads, either initially at execution service startup time, or under heavy load, may be serialized by the execution service. But an instance of
ThreadFactory
can be passed around and associated with multiple execution service. Therefore, the internal state of ThreadFactory
needs to be thread-safe and immutable.