1.ThreadLocal
为什么要remove?
因为key 设计的是弱引用,Java的弱引用的定义是,当JVM执行垃圾回收扫描的时候,当发现只有弱引用的对象时,会立即回收此对象,这是ThreadLocal当初设计的时候防止内存溢出的一个手段。
由于 value是强引用,只要 Thread不死亡时,例如线程池,这条强引用链就会存在,那么value就不会回收,可能造成内存溢出
解决方案
但是这个消除强引用链的动作是需要业务方在get的情况下触发的,可能业务方并不会get、也可能get是key不为空,并不会触发 expungeStaleEntry 类。所以开发者要养成良好的习惯,记得用完 ThreadLocal 时,调一次ThreadLocal.remove()方法或者 ThreadLocal.set(null)
public class ThreadLocalHolder {
private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
public static void setUserLocal(User user) {
userThreadLocal.set(user);
}
public static void removeUserLocal() {
userThreadLocal.set(null);
userThreadLocal.remove();
}
public static void remove() {
removeUserLocal();
}
public static void main(String[] args) throws InterruptedException {
List<Thread> threadList = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
int finalI = i;
Thread thread = new Thread(() -> {
setUserLocal(new User("name" + finalI, "P" + finalI, Collections.singleton(new JaasGrantedAuthority("a", null))));
System.out.println(JSON.toJSON(userThreadLocal.get()));
});
thread.start();
remove();
threadList.add(thread);
}
for (Thread t : threadList) {
//等所有线程执行完成后才执行 "开始执行!!!!!!"
t.join();
}
System.out.println("开始执行!!!!!!");
}
}