Below is an example showing the using of ThreadLocal :
package com.company.threadlocalexample;
import java.util.UUID;
class Context {
private String userName;
public Context(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "Context{" +
"userNameSecret='" + userName + '\'' +
'}';
}
}
class UserRepository {
String getUserNameForUserId(Integer userId) {
return UUID.randomUUID().toString();
}
}
public class ThreadLocalWithUserContext implements Runnable {
private static final ThreadLocal<Context> userContext = new ThreadLocal<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
public ThreadLocalWithUserContext(Integer userId) {
this.userId = userId;
}
@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());
}
public static void main(String[] args) {
ThreadLocalWithUserContext firstUser
= new ThreadLocalWithUserContext(1);
ThreadLocalWithUserContext secondUser
= new ThreadLocalWithUserContext(2);
new Thread(firstUser).start();
new Thread(secondUser).start();
}
}
The output is gonna be like
thread context for given userId: 1 is: Context{userNameSecret=’1e9bb75a-9b81-4485-93eb-3bec869bf3ac’}
thread context for given userId: 2 is: Context{userNameSecret=’559e06a8-e038-4268-aeb1-c0020ae800bf’}
Each of the users has its own Context, context values don’t override each other.