Java里,每个线程都有自己的ThreadLocalMap,里边存着自己私有的对象。Map的Entry里,key为ThreadLocal对象,value即为私有对象T。在spring MVC中,常用ThreadLocal保存当前登陆用户信息,这样线程在任意地方都可以取到用户信息了。

public class UserContext {
private static final ThreadLocal<UserInfo> userInfoLocal = new ThreadLocal<UserInfo>(); public static UserInfo getUserInfo() {
return userInfoLocal.get();
} public static void setUserInfo(UserInfo userInfo) {
userInfoLocal.set(userInfo);
} public static void clear() {
userInfoLocal.remove(); } }

这里,跳过ThreadLocal和ThreadLocalMap的工作原理及场景不讲,主要来说说Entry为什么是WeakReference?

/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value; Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}

  先来看看WeakReference的作用,百度一下:

WeakReference是Java语言规范中为了区别直接的对象引用(程序中通过构造函数声明出来的对象引用)而定义的另外一种引用关系。WeakReference标志性的特点是:reference实例不会影响到被应用对象的GC回收行为(即只要对象被除WeakReference对象之外所有的对象解除引用后,该对象便可以被GC回收),只不过在被对象回收之后,reference实例想获得被应用的对象时程序会返回null。

  我的理解就是,WeakReference对应用的对象userInfoLocal是弱引用,不会影响到userInfoLocal的GC行为。如果是强引用的话,在线程运行过程中,我们不再使用userInfoLocal了,将userInfoLocal置为null,但userInfoLocal在线程的ThreadLocalMap里还有引用,导致其无法被GC回收(当然,可以等到线程运行结束后,整个Map都会被回收,但很多线程要运行很久,如果等到线程结束,便会一直占着内存空间)。而Entry声明为WeakReference,userInfoLocal置为null后,线程的threadLocalMap就不算强引用了,userInfoLocal就可以被GC回收了。map的后续操作中,也会逐渐把对应的"stale entry"清理出去,避免内存泄漏。

  所以,我们在使用完ThreadLocal变量时,尽量用threadLocal.remove()来清除,避免threadLocal=null的操作。前者remove()会同时清除掉线程threadLocalMap里的entry,算是彻底清除;而后者虽然释放掉了threadLocal,但线种threadLocalMap里还有其"stale entry",后续还需要处理。

ThreadLocalMap里Entry为何声明为WeakReference?的更多相关文章

  1. ThreadLocalMap里Entry声明为WeakReference

    Java里,每个线程都有自己的ThreadLocalMap,里边存着自己私有的对象.Map的Entry里,key为ThreadLocal对象,value即为私有对象T.在spring MVC中,常用T ...

  2. Threadlocal源码分析以及其中WeakReference作用分析

    今天在看Spring 3.x企业应用开发实战,第九章 Spring的事务管理,9.2.2节ThreadLocal的接口方法时,书上有提到Threadlocal的简单实现,我就去看了下JDK1.8的Th ...

  3. ThreadLocal 内存泄漏问题深入分析

    写在前面 ThreadLocal 基本用法本文就不介绍了,如果有不知道的小伙伴可以先了解一下,本文只研究 ThreadLocal 内存泄漏这一问题. ThreadLocal 会发生内存泄漏吗? 先给出 ...

  4. 记录学习WeakReference发现的问题

    在学习ThreadLocal时发现ThreadLocalMap里的Entry使用到了WeakReference,所以重新学习WeakReference 查看相关博客例如: https://blog.c ...

  5. ThreadLocal和ThreadLocalMap源码分析

    目录 ThreadLocal和ThreadLocalMap源码分析 背景分析 定义 例子 源码分析 ThreadLocalMap源码分析 ThreadLocal源码分析 执行流程总结 源码分析总结 T ...

  6. ThreadLocal为什么要用WeakReference

    先上一张图看一下ThreadLocal的内部结构,每个Thread对象内部都维护了一个ThreadLocal.ThreadLocalMap 我们在上图看到的就是三个Thread对象内部格子的Threa ...

  7. 深入源码理解ThreadLocal和ThreadLocalMap

    一.ThreadLoacl的理解: 官方的讲: ThreadLocal是一个本地线程副本变量工具类,主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰 通俗的讲: Thre ...

  8. ThreadLocal(一):Thread 、ThreadLocal、ThreadLocalMap

    一.ThreadLocalMap是ThreadLocal的内部类.Thread持有ThreadLocalMap的引用 Entry类继承了WeakReference<ThreadLocal< ...

  9. 关于HashMap遍历,为什么要用entry

    Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Va ...

随机推荐

  1. trinitycore 魔兽服务器源码分析(二) 网络

    书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...

  2. xsd

    2018-10-08 <xsd:annotation> <xsd:documentation> <![CDATA[ 说明文档 ]]> </xsd:docume ...

  3. tomcat的缺少tcnative-1.dll的解决

    tomcat启动出现如下问题: The APR based Apache Tomcat Native library which allows optimal performance in produ ...

  4. CentOS6.9安装Python-3.6.3

    CentOS6.9上默认安装的python版本是2.6的.因为系统自带的python会被系统很多软件环境依赖使用,所以不要卸载原来的Python版本,根据需要进行安装新版本即可,本人此处安装的是3.6 ...

  5. Python day 4

    阅读目录 内容回顾: 流程控制: if分支结构: while循环控制: for循环(迭代器): ##内容回顾: #1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 ...

  6. To handling editor letter

    一般崔稿信写法: Dear Editor: Sorry for disturbing you. We’re not sure if it is the right time to contact yo ...

  7. 1.MFC架构分析

    1.架构代码文件的结构 主要由四个部分组成 1.资源文件Resource.h:主要定义资源的ID 2.预编译文件:stdafx.h 可以用来解决头文件包含冲突的问题,定义一些需要全局性包含的文件. 3 ...

  8. 05 IO和管道

    目录   三种I/O设备 把I/O重定向至文件 使用管道   知识铺垫     1)查看fd-文件描述符 (L)   ll /proc/$$/fd   在Linux中,系统打开文件时会随机分配一个编号 ...

  9. segmentController

    xml <view class="segmentedControl">     <!-- 循环遍历 -->     <block wx:for=&qu ...

  10. 第三周Access的总结

    一.问;这节课你学到了什么知识? 答:这周我学得比较少,主要是学Access的数据库进行基本的维护. 2.3数据库的基本维护 对Access定期检查,修复是整个数据库重要部分: 1.Access可修复 ...