The set of ThreadLocal
instances associated with a thread are held in private members of each Thread
. Your only chance to enumerate these is to do some reflection on the Thread
; this way, you can override the access restrictions on the thread’s fields.
Once you can get the set of ThreadLocal
, you could copy in the background threads using the beforeExecute()
and afterExecute()
hooks of ThreadPoolExecutor
, or by creating a Runnable
wrapper for your tasks that intercepts the run()
call to set an unset the necessary ThreadLocal
instances. Actually, the latter technique might work better, since it would give you a convenient place to store the ThreadLocal
values at the time the task is queued.
Update: Here’s a more concrete illustration of the second approach. Contrary to my original description, all that is stored in the wrapper is the calling thread, which is interrogated when the task is executed.
static Runnable wrap(Runnable task)
{
Thread caller = Thread.currentThread();
return () -> {
Iterable<ThreadLocal<?>> vars = copy(caller);
try {
task.run();
}
finally {
for (ThreadLocal<?> var : vars)
var.remove();
}
};
}
/**
* For each {@code ThreadLocal} in the specified thread, copy the thread's
* value to the current thread.
*
* @param caller the calling thread
* @return all of the {@code ThreadLocal} instances that are set on current thread
*/
private static Collection<ThreadLocal<?>> copy(Thread caller)
{
/* Use a nasty bunch of reflection to do this. */
throw new UnsupportedOperationException();
}