面试题答案
一键面试ThreadLocal工作原理
- 数据结构:
ThreadLocal
内部有一个ThreadLocalMap
,它是一个定制化的哈希映射。每个Thread
线程对象都有一个ThreadLocal.ThreadLocalMap
类型的成员变量threadLocals
。- 当通过
ThreadLocal
的set
方法设置值时,它会首先获取当前线程,然后从当前线程的threadLocals
中以ThreadLocal
自身作为键来存储值。
- 键值存储:
- 在
ThreadLocalMap
中,ThreadLocal
实例作为键,实际存储的值作为值。当调用ThreadLocal
的get
方法时,同样先获取当前线程,再从当前线程的threadLocals
中以ThreadLocal
实例为键获取对应的值。
- 在
- 内存回收:
ThreadLocalMap
中的键ThreadLocal
是弱引用。这意味着如果没有其他强引用指向ThreadLocal
实例,在垃圾回收时,ThreadLocal
实例会被回收。但此时ThreadLocalMap
中对应的键值对仍然存在,值会因为键不可达而造成内存泄漏。为了避免这种情况,ThreadLocal
在set
、remove
等操作时会清理那些键为null
的键值对。
多线程环境下合理使用ThreadLocal提升性能的原因
- 避免线程安全问题:
- 传统多线程访问共享资源时,需要通过加锁等机制来保证线程安全,而锁的竞争会带来性能开销。使用
ThreadLocal
后,每个线程都有自己独立的变量副本,各个线程对ThreadLocal
变量的读写操作互不干扰,无需加锁,从而提高了性能。
- 传统多线程访问共享资源时,需要通过加锁等机制来保证线程安全,而锁的竞争会带来性能开销。使用
- 减少资源竞争:
- 例如在数据库连接场景中,如果使用共享的数据库连接池,多线程竞争连接资源会很频繁。通过
ThreadLocal
为每个线程创建独立的数据库连接副本,减少了线程之间对连接资源的竞争,提高了线程执行效率。
- 例如在数据库连接场景中,如果使用共享的数据库连接池,多线程竞争连接资源会很频繁。通过
- 提高局部性:
- 每个线程操作自己的
ThreadLocal
变量副本,数据访问具有更好的局部性,缓存命中率更高,在一定程度上也能提升性能。
- 每个线程操作自己的