ThreadLocal

ThreadLocal

ThreadLocal 并不是一个 Thread,而是 Thread 的局部变量

ThreadLocal 为每一个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到相应的值,线程外则不能访问

常用方法

  • public void set(T value) 设置当前线程的局部变量
  • public T get() 获取当前线程的局部变量
  • public void remove() 删除当前线程的局部变量

使用场景

获取某个线程的上下文信息,比如用户信息、请求信息等

定义一个 BaseContext 类,提供静态方法来设置、获取和删除当前线程的上下文信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// context/BaseContext.java
public class BaseContext {

public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

public static void setCurrentId(Long id) {
threadLocal.set(id);
}

public static Long getCurrentId() {
return threadLocal.get();
}

public static void removeCurrentId() {
threadLocal.remove();
}
}

在需要使用的地方调用 BaseContext.setCurrentId(id) 来设置当前线程的上下文信息,在需要获取的地方调用 BaseContext.getCurrentId() 来获取当前线程的上下文信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// controller/UserController.java
@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@PostMapping("/login")
public Result<User> login(@RequestBody User user) {
// 设置当前线程的用户 ID
BaseContext.setCurrentId(user.getId());
return Result.success(userService.login(user));
}

@GetMapping("/info")
public Result<User> info() {
// 获取当前线程的用户 ID
Long id = BaseContext.getCurrentId();
return Result.success(userService.getById(id));
}
}

注意事项

  • ThreadLocal 变量的生命周期与线程相同,当线程结束时,ThreadLocal 变量也会被销毁
  • ThreadLocal 变量的值是线程隔离的,不同线程之间无法访问
  • ThreadLocal 变量的值是线程安全的,不同线程之间不会相互影响
  • 使用 ThreadLocal 变量时,注意及时清理,避免内存泄漏