private static ThreadFactory doBuild(ThreadFactoryBuilder builder) {
final String nameFormat = builder.nameFormat;
final Boolean daemon = builder.daemon;
final Integer priority = builder.priority;
final UncaughtExceptionHandler uncaughtExceptionHandler = builder.uncaughtExceptionHandler;
final ThreadFactory backingThreadFactory =
(builder.backingThreadFactory != null)
? builder.backingThreadFactory
: Executors.defaultThreadFactory();
final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;
return new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = backingThreadFactory.newThread(runnable);
if (nameFormat != null) {
thread.setName(format(nameFormat, count.getAndIncrement()));
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
if (uncaughtExceptionHandler != null) {
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
}
return thread;
}
};
}
Recently I have began looking into ThreadFactory
which is used by ThreadPoolExecutor
to create new threads in the thread pool. For the convenience of debugging and monitoring we don't want the threads created by the thread pool to be the default 0,1,2,3 but rather with a meaningful name.
One way to achieve this goal is to implement a customized ThreadLoad
that can set the name of thread when thread is created. Guava has got a handy builder class for customized ThreadFactory
and I wish to learn from it.
It is not hard to understand most part of this class but I am quite confused by the count
variable in the doBuild
method.
I also went to the source code of ThreadPoolExecutor#Worker
where the newThread()
of the ThreadFactory
is actually called.
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
But I am still not clear why we need an atomic variable here.
Of course I can guess the threads in the thread pool may be created in a multi-threading way thus to ensure the id of the threads not get duplicated we need the id-generator to be a atomic variable but I have got no direct evidence for this assumption yet.
Can anyone cast some light on that?
I doubt that you'll find any
direct evidence
in the code. There are only 3 possibilities:
AtomicLong
is used for thread safety reasons. But it's still indirect evidence, because author can be wrong in his assumptions (he is't).count
correctly updated in some multi-thread scenario. But it's again indirect evidence, because it states that the count
correctly updated, not that it would be incorrectly updated in other cases.AtomicLong
... Well, you can do that.But if you do understand that
the threads in the thread pool may be created in a multi-threading way thus to ensure the id of the threads not get duplicated we need the id-generator to be a atomic variable
what else do you need? The mental experiment (unlike the test from the third bullet) is quite simple:
newThread
is called from Thread1
count
count
is read, and placed in a register.count
is incremented in the register but not yet written to the memory where the count
is stored.newThread
from Thread1
is paused. newThread
is called again but from Thread2
count
Thread2
can't read the updated value of the count
from the register. It can read it from the memory, but there is still an old value.