ThreadLocal
ThreadLocal 深度解析
1. 核心概念
- 作用:为每个线程提供独立的变量副本,解决多线程并发访问共享变量的冲突问题。
- 本质:线程级别的全局变量(线程隔离的全局存储)。
2. 底层原理
1
2
3
4
5
6
7
8public class ThreadLocal<T> {
// 关键:每个Thread对象内部维护一个ThreadLocalMap
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals; // 获取线程专属的Map
map.set(this, value); // 以ThreadLocal实例为key存储值
}
}- 存储结构:
- 每个
Thread对象内部有一个ThreadLocalMap(类似HashMap但更简单)。 - Key:
ThreadLocal实例(弱引用),Value:线程的变量副本。
- 每个
3. 使用场景
场景 说明 数据库连接管理 每个线程维护独立的Connection(如Spring的 TransactionSynchronizationManager)用户会话信息 在Web应用中存储当前请求的用户信息(如Spring Security的 SecurityContextHolder)日期格式化工具 避免 SimpleDateFormat线程不安全问题4. 使用示例
1
2
3
4
5
6
7
8
9
10
11// 1. 定义ThreadLocal变量
private static final ThreadLocal<User> currentUser = ThreadLocal.withInitial(() -> null);
// 2. 设置当前线程的值
currentUser.set(user);
// 3. 获取当前线程的值
User user = currentUser.get();
// 4. 使用后必须清理!防止内存泄漏
currentUser.remove();
5. 内存泄漏问题
原因:
ThreadLocalMap的 Key 是弱引用,但 Value 是强引用。- 线程池中线程长期存活时,Value 可能无法被回收。
解决方案:
每次使用后调用
remove()清理。使用
1
try-finally
确保清理:
1
2
3
4
5
6try {
currentUser.set(user);
// 业务逻辑...
} finally {
currentUser.remove();
}
6. 与synchronized对比
特性 ThreadLocal synchronized 作用范围 线程隔离 线程互斥 性能开销 无锁,更快 有锁竞争,可能阻塞 适用场景 线程间数据隔离 线程间同步控制 7.相关问题
- Q1:ThreadLocal如何实现线程隔离?
A:每个Thread内部维护独立的ThreadLocalMap,以ThreadLocal实例为Key存储值。 - Q2:为什么Key用弱引用?
A:防止ThreadLocal对象无法被回收(但仍需手动remove()避免Value泄漏)。 - Q3:Spring如何用ThreadLocal管理事务?
A:TransactionSynchronizationManager用ThreadLocal保存当前线程的数据库连接。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WHAT AM I ?!
