Use of ThreadLocal in Java

ThreadLocal is primarily used to store data for the current thread, which only the current thread can access.

When defining a ThreadLocal, we can also define specific types of objects stored in a ThreadLocal.

ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();
Copy the code

Above we define a ThreadLocal object that stores an Integer.

Storing and retrieving objects in ThreadLocal is also very simple, using get () and set () :

threadLocalValue.set(1);
Integer result = threadLocalValue.get();
Copy the code

I can think of ThreadLocal as a map, and the current thread is the key in the map.

In addition to new a ThreadLocal object, we can also use:

    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
        return new SuppliedThreadLocal<>(supplier);
    }
Copy the code

ThreadLocal provides the static method withInitial to initialize a ThreadLocal.

ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);
Copy the code

WithInitial requires a Supplier object, which is obtained by calling the Supplier’s get() method.

To delete stored data in ThreadLocal, call:

threadLocal.remove();
Copy the code

Let me compare two examples to see the benefits of using ThreadLocal.

In practical applications, we usually need to store different user information for different user requests. Generally speaking, we need to build a global Map to store different user information according to different user ids, which is convenient to obtain later.

Store user data in a Map

Let’s first look at how to use a global Map:

public class SharedMapWithUserContext implements Runnable {

    public static Map<Integer, Context> userContextPerUserId
            = new ConcurrentHashMap<>();
    private Integer userId;
    private UserRepository userRepository = new UserRepository();

    public SharedMapWithUserContext(int i) {
        this.userId=i;
    }

    @Override
    public void run(a) {
        String userName = userRepository.getUserNameForUserId(userId);
        userContextPerUserId.put(userId, newContext(userName)); }}Copy the code

Here we define a static Map to access user information.

Here’s how to use it:

    @Test
    public void testWithMap(a){
        SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1);
        SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2);
        new Thread(firstUser).start();
        new Thread(secondUser).start();
        assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2);
    }
Copy the code

Store user data in ThreadLocal

If we want to use ThreadLocal we can do this:

public class ThreadLocalWithUserContext implements Runnable {

    private static ThreadLocal<Context> userContext
            = new ThreadLocal<>();
    private Integer userId;
    private UserRepository userRepository = new UserRepository();

    public ThreadLocalWithUserContext(int i) {
        this.userId=i;
    }

    @Override
    public void run(a) {
        String userName = userRepository.getUserNameForUserId(userId);
        userContext.set(new Context(userName));
        System.out.println("thread context for given userId: "
                + userId + " is: "+ userContext.get()); }}Copy the code

The test code is as follows:

public class ThreadLocalWithUserContextTest {

    @Test
    public void testWithThreadLocal(a){
        ThreadLocalWithUserContext firstUser
                = new ThreadLocalWithUserContext(1);
        ThreadLocalWithUserContext secondUser
                = new ThreadLocalWithUserContext(2);
        new Thread(firstUser).start();
        newThread(secondUser).start(); }}Copy the code

After running, we get the following result:

thread context for given userId: 1 is: com.flydean.Context@411734d4
thread context for given userId: 2 is: com.flydean.Context@1e9b6cc
Copy the code

Different user information is stored in different thread environments.

Note that when we use ThreadLocal, we must have free control over the threads we create. It is best not to use ThreadLocal in an ExecutorService environment, where threads are uncontrollable.

Examples of this article can be found at github.com/ddean2009/l…

See flydean’s blog for more tutorials