Search code examples
javamultithreadingthread-local

Is it dangerous to use ThreadLocal with ExecutorService?


I was going through the concept of ThreadLocals on the below blog :

https://www.baeldung.com/java-threadlocal

It says that "Do not use ThreadLocal with ExecutorService"

It illustrates below example for using ThreadLocals.

public class ThreadLocalWithUserContext implements Runnable {
  
    private static ThreadLocal<Context> userContext 
      = new ThreadLocal<>();
    private Integer userId;
    private UserRepository userRepository = new UserRepository();
 
    @Override
    public void run() {
        String userName = userRepository.getUserNameForUserId(userId);
        userContext.set(new Context(userName));
        System.out.println("thread context for given userId: "
          + userId + " is: " + userContext.get());
    }
     
    // standard constructor
}

At the End of the post it mentions that :

If we want to use an ExecutorService and submit a Runnable to it, using ThreadLocal will yield non-deterministic results – because we do not have a guarantee that every Runnable action for a given userId will be handled by the same thread every time it is executed.

Because of that, our ThreadLocal will be shared among different userIds. That’s why we should not use a TheadLocal together with ExecutorService. It should only be used when we have full control over which thread will pick which runnable action to execute.

This explanation was a bouncer to me. I tried to do some research online for this point specifically but I could not get much help, can some expert please elaborate on the above explanation? Is it authors view or a real Threat?


Solution

  • 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.