先上一张图看一下ThreadLocal的内部结构,每个Thread对象内部都维护了一个ThreadLocal.ThreadLocalMap

我们在上图看到的就是三个Thread对象内部格子的ThreadLocalMap

这里要说的不是ThreadLocal,是ThreadLocal为什么要用WeakReference

static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}

弱引用WeakReference

弱引用只要发生了gc就会被回收,但前提是只有弱引用,没有强引用(这点本身也不容易做到)

WeakReference<Apple> weakReference = new WeakReference<>(new Apple("1"));
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(weakReference.get());//
System.gc();//遇到gc就回收了
System.out.println(weakReference.get());//null

引用传递的特殊情况

1、传递的入参是null,方法内new了,也不会影响到外面null的对象,还是null的
2、传递的入参不是null,方法内=null了,也不会影响到外面不是null的对象
3、传递的入参不null,传递到线程中,线程运行中,外面把入参设置为null,线程内继续不是null
总结,别管里面外面 null变!null !null变null 都不会隔层影响原来啥样还啥样

  //我们在这里只插入一段模拟线程运行的情况
……
obj = new ObjectPassing();
obj.setName("name");
MyThread myThread = new MyThread(obj);//obj不是空的传入新线程
new Thread(myThread).start();//线程不停的打印obj的name字段值
Thread.sleep(1000);
obj = null;//将外面的obj置为空后,线程打印的仍然不为空,这点需要先明确
System.out.println("2:"+obj); Thread.sleep(1000000);
} public void testNullPassFunc(ObjectPassing obj){
obj = new ObjectPassing();
obj.setName("zxp");
System.out.println("2:"+obj);
} public void testNullPassFunc2(ObjectPassing obj){
obj = null;
System.out.println("2:"+obj);
} @Data
static class ObjectPassing{
private String name;
} 1:null
2:ParameterPassing.ObjectPassing(name=zxp)
3:null
=======================
1:ParameterPassing.ObjectPassing(name=name)
2:null
3:ParameterPassing.ObjectPassing(name=name)
=======================
1:name
1:name
2:null
1:name
1:name
1:name
……
public class MyThread implements Runnable {
ParameterPassing.ObjectPassing objectPassing = null;
public MyThread(ParameterPassing.ObjectPassing objectPassing){
this.objectPassing = objectPassing;
} @Override
public void run() {
while (true){
System.out.println("1:"+objectPassing.getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

分析ThreadLocal与WeakReference

分析一下为什么ThreadLocal要用WeakReference 不用有什么问题

ThreadLocal local = new ThreadLocal();
local.set("当前线程名称:"+Thread.currentThread().getName());//将ThreadLocal作为key放入threadLocals.Entry中
Thread t = Thread.currentThread();//注意断点看此时的threadLocals.Entry数组刚设置的referent是指向Local的,referent就是Entry中的key只是被WeakReference包装了一下
local = null;//断开强引用,即断开local与referent的关联,但Entry中此时的referent还是指向Local的,为什么会这样,当引用传递设置为null时无法影响传递内的结果
System.gc();//执行GC
t = Thread.currentThread();//这时Entry中referent是null了,被GC掉了,因为Entry和key的关系是WeakReference,并且在没有其他强引用的情况下就被回收掉了
//如果这里不采用WeakReference,即使local=null,那么也不会回收Entry的key,因为Entry和key是强关联
//但是这里仅能做到回收key不能回收value,如果这个线程运行时间非常长,即使referent GC了,value持续不清空,就有内存溢出的风险
//彻底回收最好调用remove
//即:local.remove();//remove相当于把ThreadLocalMap里的这个元素干掉了,并没有把自己干掉
System.out.println(local);

ThreadLocal为什么要用WeakReference的更多相关文章

  1. Android 异步消息处理机制前篇(一):深入理解ThreadLocal

    版权声明:本文出自汪磊的博客,转载请务必注明出处. ThreadLocal简介 ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获 ...

  2. 深入学习ThreadLocal原理

    上文我们学习了ThreadLocal的基本用法以及基本原理,ThreadLocal中的方法并不多,基本用到的也就get.set.remove等方法,但是其核心逻辑还是在定义在ThreadLocal内部 ...

  3. ThreadLocal 简介 案例 源码分析 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. ThreadLocal 的机制与内存泄漏

    ThreadLocal笔记 如上图所示 每个Thread 都有一个map,里面存着Entry<Key,value>,而key是实现了WeakReference的ThreadLocal,如果 ...

  5. Java面试题必备知识之ThreadLocal

    老套路,先列举下关于ThreadLocal常见的疑问,希望可以通过这篇学习笔记来解决这几个问题: ThreadLocal是用来解决什么问题的? 如何使用ThreadLocal? ThreadLocal ...

  6. Netty源码分析-- ThreadLocal分析(九)

    为了更好地探讨Netty的内存模型,后面会用到,这里我还是决定跟大家一起看下ThreadLocal和FastThreadLocal的源码,有的时候我们在看源码的时候会一层层的遇到很多之前没有看过的内容 ...

  7. java并发编程(二十六)----ThreadLocal的使用

    其实ThreadLocal很多接触过多线程的同学都可能会很陌生,他不像current包里面那些耳熟能详的api一样在我们面前经常出现,更多的他作为一个本地类出现在系统设计里面.我们可以说一下Sprin ...

  8. 基础篇:JAVA引用类型和ThreadLocal

    前言 平时并发编程,除了维护修改共享变量的场景,有时我们也需要为每一个线程设置一个私有的变量,进行线程隔离,java提供的ThreadLocal可以帮助我们实现,而讲到ThreadLocal则不得不讲 ...

  9. 从源码看Thread&ThreadLocal&ThreadLocalMap的关系与原理

    1.三者的之间的关系 ThreadLocalMap是Thread类的成员变量threadLocals,一个线程拥有一个ThreadLocalMap,一个ThreadLocalMap可以有多个Threa ...

随机推荐

  1. springMVC容器加载源码分析

    springmvc是一个基于servlet容器的轻量灵活的mvc框架,在它整个请求过程中,为了能够灵活定制各种需求,所以提供了一系列的组件完成整个请求的映射,响应等等处理.这里我们来分析下spring ...

  2. Python制作NTF传递函数工况文件和后处理文件

    摘要:在平时工作中,TB车身的传递函数分析,涉及到大量重复行的工作,费时费力.在学习python基础后,希望通过代码解决这部分重复工作.基础入门级操作,但是能够解决很大一部分工作内容.日后,待pyth ...

  3. require、require_once、include、include_once

    在 PHP 中,您可以在服务器执行 PHP 文件之前在该文件中插入一个文件的内容. include 和 require 语句用于在执行流中插入写在其他文件中的有用的代码. include 和 requ ...

  4. Java基础笔记(十三)——面向对象

    类和对象 类是具有相同属性和方法的一组对象的集合,好比一个虚拟的轮廓(抽象的概念),确定对象将会拥有的特征(属性)和行为(方法). 对象是类的实例表现,是一个具体的东西(一个看得到.摸得着的具体实体) ...

  5. Ehab and subtraction(思维题)

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  6. P2308 添加括号(区间DP)

    题目背景 给定一个正整数序列a(1),a(2),...,a(n),(1<=n<=20) 不改变序列中每个元素在序列中的位置,把它们相加,并用括号记每次加法所得的和,称为中间和. 例如: 给 ...

  7. python+selenium之多窗口切换

    #打开浏览器driver = webdriver.Firefox()driver.get(url)#获取当前窗口now_handle=driver.current_window_handle # 获取 ...

  8. iOS开发 - 3D Touch 应用系列一 - Quick Actions 创建桌面 Icon 快捷方式

    个言 很久没发随笔了,有一年多了吧.期间也曾想继续去写随笔,但是因为各种原因而耽搁了.最近又想了一下,还是有很多东西想要写,想要分享,想要记录下来的东西.之后我也会不断写随笔,但不止于 iOS 的方向 ...

  9. 有限状态机在单片机和 Arduino 编程中的应用

    有限状态机在单片机和 Arduino 编程中的应用,个人认为在实际中这是一种思想,意味着解决一类问题. 本帖最后由 张飞 于 2015-3-4 20:18 编辑 在单片机编程中,如果在不使用操作系统的 ...

  10. jQuery判断动画是否执行完成

    JS $(function() { $("#myDiv").bind("click", function() { if ($(this).css("t ...