David David - 8 months ago 92
Java Question

Is ThreadLocal safe to use with Tomcat NIO Connector

This just came to mind when testing the Tomcat NIO connector during my load tests. I make use of ThreadLocal's additionally I use Spring, which I know in several places it also makes use of it.

Since the NIO connector does not have a thread per connection, I worry that it may result in very hard to find bugs if a ThreadLocal object was shared with another thread before it had been cleaned up. However, I assume that this is not an issue as it is not a documented warning that I could find, nor have I found any other posts warning about this. I assume that the NIO connector has no effect to the threads that serve the actual requests.

Before I go with this assumption, I was hoping to find some concrete proof.


Only someone familiar with the Tomcat code will be able to give you a concrete answer, but I'll try a wooden one :)

Firstly, you need to be clear whether you mean simply using NIO connectors or whether you're also talking about Async servlets. The answer will be slightly different in each case.

The main thing to be aware of is that Java doesn't have any sort of continuations, co-routines or thread-rescheduling. Which means that once you launch a piece of code running on a thread, only that piece of code will run on the thread until it completes.

So if you have: myObject.doSomething(); then for the time doSomething runs, it has exclusive access to that thread. The thread is not going to switch to some other piece of code - regardless of what sort of IO model you're using.

What might (will) happen is that different threads will be scheduled to run on different CPUs, but each thread will run one piece of code to completion.

So if doSomething is:

public static final ThreadLocal<MyClass> VALUE = new ThreadLocal<MyClass>();
public void doSomething() {
  try {
  } finally {

then there's nothing to worry about - doSomethingElse will run one a single thread and the threadlocal will be set to the right value for the whole execution.

So a simple NIO connector should make no difference - the container will call the service method on the servlet, the servlet will execute in a single thread, and then at the end it's all done. It's just that the container is able to process the IO in a more efficient way as it handles the connections.

If you're using async servlets then it's a little different - in that case your servlet might get called multiple times for a single request (because of the way the asynchronous model works), and those calls might be on different threads, so you can't store something in a thread-local between invocations of your servlet. But for a single call to your service method, it's still fine.