The ThreadLocal and ThreadPool don't interact with one another unless you do this.
What you can do is a a single ThreadLocal which stores all the state you want to hold and have this be reset when the task completes. You can override ThreadPoolExecutor.afterExecute (or beforeExecute) to clear your ThreadLocal(s)
From ThreadPoolExecutor
/**
* Method invoked upon completion of execution of the given Runnable.
* This method is invoked by the thread that executed the task. If
* non-null, the Throwable is the uncaught {@code RuntimeException}
* or {@code Error} that caused execution to terminate abruptly.
*
* <p>This implementation does nothing, but may be customized in
* subclasses. Note: To properly nest multiple overridings, subclasses
* should generally invoke {@code super.afterExecute} at the
* beginning of this method.
*
... some deleted ...
*
* @param r the runnable that has completed
* @param t the exception that caused termination, or null if
* execution completed normally
*/
protected void afterExecute(Runnable r, Throwable t) { }
Rather than keep track of all ThreadLocals, you could clear them all at once.
protected void afterExecute(Runnable r, Throwable t) {
// you need to set this field via reflection.
Thread.currentThread().threadLocals = null;
}