One of the rarely known features in Java among developers is Thread-local storage. The idea is simple, and the need for it comes in scenarios where we need data that is, well, local for the thread. For example, if we have two threads that refer to the same global variable but we want them to have separate values independently initialized of each other.

Most major programming languages have implementations of the concept. For example, C++11 has the thread local keyword, and Ruby has chosen an API approach.

In the beginning the value is set to null to both threads, obviously each of them works with separate values since after setting the value to System.nanoTime() on Thread-0 it will not have any effect on the value of Thread-1 exactly as we wanted, a thread scoped long variable. One nice side effect is a case where the thread calls multiple methods from various classes. They will all be able to use the same thread scoped variable without major API changes. Since the value is not explicitly passed through one might argue it difficult to test and bad for design, but that is a separate topic altogether.

In what areas are popular frameworks using Thread Locals?

Spring, being one of the most popular frameworks in Java, uses ThreadLocals internally for many parts - easily demonstrated by a simple GitHub search. Most of the usages are related to the current user's actions or information. This is actually one of the main uses for ThreadLocals in JavaEE world, storing information for the current request like in RequestContextHolder:

Or the current JDBC connection user credentials in UserCredentialsDataSourceAdapter. If we get back on RequestContextHolder, we can use this class to access all of the current request information from anywhere in our code. A common use case for this is LocaleContextHolder, which helps us store the current user's locale. Mockito uses it to store the current "global" configuration and if we take a look at any framework out there is a high chance we'll find it as well.

Thread Locals and Memory Leaks

Now that we've learned about this awesome little feature, let's use it all over the place! Well, we can do that, but if you try a few Google searches, you'll find that most posts out there claim that ThreadLocal is evil. That's not exactly true. It's a nice utility, but in some contexts, you could easily accidentally create a memory leak.

“Can you cause unintended object retention with thread locals? Sure you can. But you can do this with arrays too. That doesn’t mean that thread locals (or arrays) are bad things. Merely that you have to use them with some care. The use of thread pools demands extreme care. Sloppy use of thread pools in combination with sloppy use of thread locals can cause unintended object retention, as has been noted in many places. But placing the blame on thread locals is unwarranted.” - Joshua Bloch

It is very easy to create a memory leak in your server code using ThreadLocal if it runs on an application server. ThreadLocal context is associated to the thread where it runs and will be garbaged once the thread is dead. Modern app servers use pool of threads instead of creating new ones on each request, meaning you can end up holding large objects indefinitely in your application. Since the thread pool is from the app server, our memory leak could remain even after we unload our application. The fix for this is simple - free up resources you do not need. One other ThreadLocal misuse is API design. Often I have seen use of RequestContextHolder(that holds ThreadLocal) all over the place, like the DAO layer, for example. Later on, if one were to call the same DAO methods outside a request, for instance, and scheduler, he would get a very bad surprise. Even though, the variables in ThreadLocal are local to the thread they are very much global in your code. So, if you want to avoid maintenance developers hunting you down and taking their revenge, make sure you really need this thread scope before you use it.

Popular posts from this blog

It is always tempting to add custom attributes in HTML so that you can use the data stored there to do X. But if you do that there is no way of knowing if your HTML attribute will not be overridden in the future and used for something else and additionally you will not be writing valid HTML markup that can pass HTML 5 validator and with that you can create some very bad side effects. That is why there is a spec in HTML 5 called custom data attributes that enable number of useful features.

You may go around and read the specs, but the basic idea is very simple, you can add any attribute that starts with "data-" and that attribute will be treated as non-visible data for that attribute. By non-visible I mean that it is not something that gets rendered to the client so it does not affect the layout or style of the page, but it is there in the HTML so in no way this is private.
So let's get right into it, the following snippet is a valid HTML5 markup

Spring Rest Templates are very good way of writing REST clients. By default they work with basic HTTP so if we need to use Basic Authorization we would need to init the rest template with custom HttpClient. This way the Rest Template will automatically use Basic Auth and append to the HTTP headers "Authorization: Basic BASE64ENCODED_USER_PASS".

Sometimes we want to create a temporary file, whether to save some data that gets written by some other application or just to temporary store stuff. Well, usually applications have their own temporary folder where they do this and it gets somehow configured. But why not use the underlying OS specific file like "/tmp/" in Linux so there must be some system property that has this info and there is. The key is "java.io.tmpdir" resulting in "/tmp" in my case or by code:
String tempDir = System.getProperty("java.io.tmpdir");
We can use tempDir folder as a temporary place to store files, but there are a lot nicer ways to work with files like this even in JDK6 not just in JDK7:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TempFile {
public static void main(String[] args) {
try {
// create a temp file
File tempFile = File.createTempFile("old-file",…