Preface
ThreadLocal is mainly used to store data for the current thread, this data is only accessible by the current thread.
When defining a ThreadLocal, we can also define specific types of objects stored in the ThreadLocal.
1
|
ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();
|
Above we have defined a ThreadLocal object that stores an Integer.
To store and get the object in ThreadLocal is also very simple, using get() and set().
1
2
|
threadLocalValue.set(1);
Integer result = threadLocalValue.get();
|
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 create a ThreadLocal object by.
1
2
3
|
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
return new SuppliedThreadLocal<>(supplier);
}
|
ThreadLocal provides the static method withInitial to initialize a ThreadLocal.
1
|
ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);
|
withInitial requires a Supplier object, which gets its initial value by calling the Supplier’s get() method.
To remove the stored data from the ThreadLocal, call.
I’ll look at the benefits of using ThreadLocal by comparing two examples.
In a real application, we usually need to store different user information for different user requests. Generally we need to build a global Map to store different user information based on different user IDs for easy access later.
Storing user data in a Map
Let’s see how to use the global Map if we use.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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() {
String userName = userRepository.getUserNameForUserId(userId);
userContextPerUserId.put(userId, new Context(userName));
}
}
|
Here we have defined a static Map to access user information.
To see how it can be used again.
1
2
3
4
5
6
7
8
|
@Test
public void testWithMap(){
SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1);
SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2);
new Thread(firstUser).start();
new Thread(secondUser).start();
assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2);
}
|
Storing user data in ThreadLocal
If we want to use in ThreadLocal we can do this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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() {
String userName = userRepository.getUserNameForUserId(userId);
userContext.set(new Context(userName));
System.out.println("thread context for given userId: "
+ userId + " is: " + userContext.get());
}
}
|
The test code is as follows.
1
2
3
4
5
6
7
8
9
10
11
12
|
public class ThreadLocalWithUserContextTest {
@Test
public void testWithThreadLocal(){
ThreadLocalWithUserContext firstUser
= new ThreadLocalWithUserContext(1);
ThreadLocalWithUserContext secondUser
= new ThreadLocalWithUserContext(2);
new Thread(firstUser).start();
new Thread(secondUser).start();
}
}
|
After running it, we get the following result.
1
2
|
thread context for given userId: 1 is: com.javaisland.Context@2eabdvc
thread context for given userId: 2 is: com.javaisland.Context@1e9b6cc
|
Different user information is stored in different thread contexts.
Note that when we use ThreadLocal, we must be free to control the threads we create. If you are in an ExecutorService environment, it is better not to use ThreadLocal, because in ExecutorService, threads are not controllable.
If you want to learn more about the use of threadlocal, please continue to see another article:A scenario using Threadlocal to solve concurrency and efficiency problems