不同ThreadLocal引用同一对象的行为分析及给定Java代码执行逻辑问询
不同ThreadLocal引用同一对象的行为分析及给定Java代码执行逻辑问询
嗨,我来帮你理清楚这段代码的逻辑,还有你没说完的线程修改对象的问题~
首先拆解这段代码到底做了什么:
- 首先定义了一个静态的
SomeClass实例someInstance,静态成员属于类本身,意味着整个应用里所有线程共享这同一个对象引用。 - 然后创建了一个
ThreadLocal实例locals,它的作用是给每个线程存储独立的HashMap<Integer, SomeClass>对象。 - 重写了
ThreadLocal的initialValue方法,这里用了大家常说的「双大括号初始化」(本质是匿名内部类+实例初始化块的写法),返回的HashMap里默认存入了键为5、值为那个静态someInstance的条目。
接下来回答你没说完的核心问题:如果线程1通过自己的ThreadLocal拿到这个HashMap,再取出someInstance并修改它的状态,会发生什么?
划重点:每个线程的ThreadLocal里确实有自己独立的HashMap,但这些HashMap里存的someInstance是同一个对象!
- ThreadLocal的作用是让每个线程拥有自己专属的「容器」(这里就是HashMap),但容器里装的东西是共享的静态实例。
- 所以线程1修改
someInstance的成员变量或者状态后,不管是其他线程直接访问someInstance,还是通过自己的ThreadLocal里的HashMap取出这个实例,看到的都会是修改后的状态——因为它们指向的是内存里同一个对象。
另外提个小细节:这种双大括号初始化的写法虽然简洁,但会创建匿名内部类,可能会意外持有外部类的引用,带来内存泄漏风险。如果是生产环境代码,更推荐用普通的初始化方式:
@Override protected HashMap<Integer, SomeClass> initialValue() { HashMap<Integer, SomeClass> map = new HashMap<>(); map.put(5, someInstance); return map; }
备注:内容来源于stack exchange,提问作者Hex_27
相关产品推荐
相关产品推荐

