Is it dangerous to use ThreadLocal with ExecutorService?

The point of that caution is that multiple runs of your Runnable may execute on different threads. An executor service can be backed by a single thread but it may just as well be backed by a pool of threads. On subsequent executions of your Runnable, a different thread will be accessing a different ThreadLocal.

So you certainly can use ThreadLocal within a single run of the Runnable. But it is not likely to be useful, as generally the purpose of a ThreadLocal is to hold a value for a while. In contrast, a Runnable should generally be short-lived.

So, no, generally it does not make sense to use a ThreadLocal with a thread pool.


Consider a ThreadLocal to be some sort of "in memory cache" for code that is executed by the same thread. The exact same thread. It is a bad idea to share a ThreadLocal between code that is executed on different threads.

Tha javadoc clearly states:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

In other words: the goal of using ThreadLocals is to give "each" code running in different threads "thread specific" data.

ExecutorService on the other hand is first of all an interface: you simply don't know if it is powered by a single thread, or (much more likely) by multiple threads.

In other words: using an ExecutorService quickly leads to multiple different threads running your Runnables/Tasks. And then you would be sharing your ThreadLocal amongst these multiple threads.

So, "dangerous" is maybe the wrong word. The goal of using ThreadLocal is to have per-thread storage, whereas an ExecutorService is about code being executed by an unknown number of threads. Those two things are simply not going together nicely.

The focus is different: one concept emphasises a long living thread connected to a very specific "activity". The other concept is about executing small, independent activities using an unknown number of namesless threads.