标签:不为 lse 静态内部类 key extend 控制台 cal 数据 efault
ThreadLocal 叫做线程变量,在 ThreadLocal 中填充的变量属于 当前 线程,该变量对其他线程而言是隔离的。ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
ThreadLocal 和 Synchronized 都是为了解决多线程中相同变量的访问冲突问题,不同的点是
// 设置值
void set(T value);
// 获取值
T get();
// 删除值
void remove();
// 设置默认缺省值
T initialValue();
public static void main(String[] args) {
ThreadLocal<Integer> defaultValueLocal = new ThreadLocal() {
public Integer initialValue() {
return 1;
}
};
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
final Integer result = defaultValueLocal.get();
System.out.println(Thread.currentThread().getName()+ " --> result=" + result);
}
});
thread.start();
}
}
控制台输出:
Thread-0 --> result=1
Thread-1 --> result=1
Thread-2 --> result=1
Thread-3 --> result=1
Thread-4 --> result=1
Thread-5 --> result=1
Thread-6 --> result=1
Thread-7 --> result=1
Thread-8 --> result=1
Thread-9 --> result=1
public static void main(String[] args) {
ThreadLocal<String> nameLocal = new ThreadLocal<>();
for (int i = 0; i < 10; i++) {
int finalI = i;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
nameLocal.set(Thread.currentThread().getName() + " -->" + finalI);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前线程输出:" + nameLocal.get());
}
});
thread.start();
}
}
控制台输出:
当前线程输出:Thread-2 -->2
当前线程输出:Thread-1 -->1
当前线程输出:Thread-0 -->0
当前线程输出:Thread-3 -->3
当前线程输出:Thread-9 -->9
当前线程输出:Thread-8 -->8
当前线程输出:Thread-7 -->7
当前线程输出:Thread-6 -->6
当前线程输出:Thread-5 -->5
当前线程输出:Thread-4 -->4
public void set(T value) {
// 获取当前线程对象
Thread t = Thread.currentThread();
// 获取 ThreadLocalMap 对象
ThreadLocalMap map = getMap(t);
// 判断 ThreadLocalMap 对象是否存在
if (map != null)
// 存在,则设置值到 ThreadLocalMap 中
map.set(this, value);
else
// 否则创建 ThreadLocalMap 对象
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
**ThreadLocalMap ** 对象是 ThreadLocal 的一个静态内部类,里面定义了一个 Entry 来保存数据,而且还是继承的弱引用。在 Entry 内部使用 ThreadLocal 作为key,使用我们设置的 value 作为 value:
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
public T get() {
// 获取当前线程对象
Thread t = Thread.currentThread();
// 获取 ThreadLocalMap 对象
ThreadLocalMap map = getMap(t);
// 判断 ThreadLocalMap 对象是否存在
if (map != null) {
// 获取当前线程存储变量
ThreadLocalMap.Entry e = map.getEntry(this);
// 变量不为空时,将值返回
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// ThreadLocalMap 对象不存在或不存在指定KEY值时,返回默认值
return setInitialValue();
}
// 设置初始默认值
private T setInitialValue() {
// 调用初始默认值设置函数
T value = initialValue();
// 将初始默认值存储到 ThreadLocalMap 对象中
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
protected T initialValue() {
// 默认返回 null,按需覆盖
return null;
}
在上面我们介绍 ThreadLocal 源码的时候,了解到 ThreadLocal 通过 ThreadLocalMap 对象存储值,它的 key 存储的是当前的 ThreadLocal 的引用,属于弱引用。当 ThreadLocal 被回收时,value 却还存在,就会造成内存泄漏。
解决办法: 在使用完 ThreadLocal 后,执行 remove 操作,避免出现内存溢出情况。
标签:不为 lse 静态内部类 key extend 控制台 cal 数据 efault
原文地址:https://www.cnblogs.com/markLogZhu/p/13852525.html