1.何为ThreadLocal?
ThreadLocal为解决多线程并发问题提供了一个新的解决方式。ThreadLocal并不是Thread,而是Thread的一个局部变量。
使用场景那也是相当的丰富:
1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
2、线程间数据隔离
3、进行事务操作,用于存储线程事务信息。
4、数据库连接,Session会话管理。
2.ThreadLocal的实现原理
ThreadLocal起作用的根源是Thread类:
public class Thread implements Runnable {
......(其他源码)
/*
* 当前线程的ThreadLocalMap,主要存储该线程自身的ThreadLocal
* 本文主要讨论的就是这个ThreadLocalMap
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal,自父线程集成而来的ThreadLocalMap,
* 主要用于父子线程间ThreadLocal变量的传递
* 此处我们不过多解释inheritableThreadLocals变量
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
......(其他源码)
}
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
ThreadLocalMap是ThreadLocal类的一个静态内部类,它实现了键值对的设置和获取(对比Map对象来理解),每个线程中都有一个独立的ThreadLocalMap副本,它所存储的值,只能被当前线程读取和修改。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。还有一点就是,ThreadLocalMap存储的键值对中的键是this对象指向的ThreadLocal对象,而值就是你所设置的对象了。
Threadlocal里面使用了一个存在弱引用的map,当释放掉threadlocal的强引用以后,map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露.
总结
ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,单大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。
ThreadLocal不能使用基本数据类型,只能使用Object类型。
参考文献
https://www.jianshu.com/p/3bb70ae81828
ThreadLocal是Java中用于线程间数据隔离的工具,每个线程都有自己的ThreadLocal副本,避免并发问题。它通过ThreadLocalMap实现线程局部变量存储,避免了同步带来的性能开销。然而,如果不正确使用可能导致内存泄漏。ThreadLocal适用于存储线程内的对象,如事务信息、Session管理等,但不适用于基本类型。
2381

被折叠的 条评论
为什么被折叠?



