在使用ThreadLocal时,每个线程都会有一个独立的ThreadLocal变量副本,每个线程对该变量的操作互不影响。但是,当我们重写ThreadLocal的initialValue方法时,如果返回的是同一个对象实例,不同线程在调用get方法时获取到的确实是同一个对象。
这是因为ThreadLocal中维护了一个Map,Map的键是ThreadLocal实例对象,值是每个线程独立的变量副本。当调用get方法时,ThreadLocal会通过当前线程获取对应的变量副本。如果initialValue方法返回的是同一个对象实例,那么这个对象实例就会被所有线程共享。
例如,以下是一个使用ThreadLocal的示例代码:
ThreadLocal<MyObject> myThreadLocal = new ThreadLocal<MyObject>() {
@Override
protected MyObject initialValue() {
return new MyObject(); // 返回同一个对象实例
}
};
public class MyObject {
// ...
}
// 在不同线程中获取ThreadLocal变量
Thread thread1 = new Thread(() -> {
MyObject obj = myThreadLocal.get();
// 对obj进行操作…
});
Thread thread2 = new Thread(() -> {
MyObject obj = myThreadLocal.get();
// 对obj进行操作...
});
thread1.start();
thread2.start();
在上述示例中,无论是thread1还是thread2,在调用myThreadLocal.get()获取变量副本时,得到的都是同一个MyObject对象实例。这是因为initialValue方法返回的是同一个对象,所以所有线程共享这个对象。
如果我们希望每个线程都获取到不同的对象实例,可以在initialValue方法中返回一个新的对象,而不是同一个对象实例。例如:
ThreadLocal<MyObject> myThreadLocal = new ThreadLocal<MyObject>() {
@Override
protected MyObject initialValue() {
return new MyObject(); // 返回新的对象实例
}
};
这样,每个线程在调用get方法时都会获取到一个独立的对象实例。