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. python 06函数

    python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字test:函数名( ...

  2. Java多线程系列2 线程常见方法介绍

    守护线程 执行一些非业务方法,比如gc.当全部都是守护线程的时候,jvm退出 线程优先级  设置线程优先级:setPriority(int priorityLevel).参数priorityLevel ...

  3. # 2019-2020-3 《Java 程序设计》第二周学习总结

    2019-2020-3 <Java 程序设计>第二周学习总结 1.通过第二周的学习,利用教材和老师在蓝墨云上的一些教学视频以及通过老师和同学的博客以及一些课外资料,充分学习了第二.三章的内 ...

  4. 1001. A+B Format 字符串

    题目及答案链接 https://www.liuchuo.net/archives/1888 c++ 有关 字符串 和各种类型的转换 #include <string> string a; ...

  5. python闭包和延迟绑定

    一.什么是闭包: 1.函数内定义函数. 2.外函数的返回时内函数的引用. 3.内函数使用外函数的局部变量(至少一个). 1 def outfunc(): 2 for num in range(4): ...

  6. Makefile入门

    相信大家对makefile都不陌生,在Linux下编写程序基本都离不开makefile的编写,我们都知道多个.c文件经过编译器编译后得到多个.o文件,这些文件是互相独立的,但最终我们要得到一个可正常运 ...

  7. AndroidStudio制作底部导航栏以及用Fragment实现切换功能

    前言 大家好,给大家带来AndroidStudio制作底部导航栏以及用Fragment实现切换功能的概述,希望你们喜欢 学习目标 AndroidStudio制作底部导航栏以及用Fragment实现切换 ...

  8. [CocoaPods]Podfile文件

    Podfile是一个描述一个或多个Xcode项目的目标依赖项的规范.该文件应该只是命名Podfile.指南中的所有示例都基于CocoaPods 1.0及更高版本. Podfile可以非常简单,这会将A ...

  9. OpenCL科普及在ubuntu 16.04 LTS上的安装

    OpenCL(Open Computing Language,开放计算语言)是一个为异构平台编写程序的框架,此异构平台可由CPU.GPU.DSP.FPGA或其他类型的处理器與硬體加速器所组成.Open ...

  10. 国外青少年最喜爱的聊天 app,竟然是 Google Docs

    简评: 这还真不是标题党,Google Docs 的协作中内置了实时聊天的功能,也可以进行 comments,颇有种现代「传纸条」的既视感.其实国内的石墨文档.腾讯文档等协作工具也有类似的效果,本文很 ...