ThreadLLocal的学习

ThreadLocal的学习

  • ThreadLocal的学习
    • 1.ThreadLocal是什么?
    • 2.ThreadLocal的数据结构
      • Java的四种引用类型
    • 3.ThreadLocal为什么会出现内存泄露?
      • 既然会出现内存泄露为什么Entry的key还要使用弱引用?
      • 如何避免内存泄露?

ThreadLocal的学习

1.ThreadLocal是什么?

ThreadLocal对象可以提供局部变量,每个线程Thread拥有一份自己的副本变量,每个线程Thread拥有一份自己的副本变量,多个线程互不干扰。

2.ThreadLocal的数据结构

Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadlocals

也就是说每个线程都有一个自己的ThreadLocalMap

ThreadLocal.ThreadLocalMap threadLocals=null;

ThreadLocalMap中维护了k-v形式的Entry对象

其中key视为ThreadLocal,value就是我们在ThreadLocal中存储的值

ThreadLocalMap有点类似HashMap的结构,只是HashMap是由数组+链表实现的,而ThreadLocalMap中没有链表结构

注意:

key并不是ThreadLocal本身,而是它的一个弱引用(因为继承自WeakReference

由此,ThreadLocal本身是不存储值的,我们在使用其对应的set和get方法的时候都是操作的其对应的ThreadLocalMap对象。

也就是说每个线程在往ThreadLocal里存值的时候都会往自己的ThreadLocalMap里存,读也是以ThreadLocal作为引用,在自己的map里找对应的key。这就是线程隔离

Java的四种引用类型

Java中由值类型也有引用类型,引用类型一般是针对Java中的对象来说的。

Java为引用类型专门定义了一个类叫做Reference

Reference是跟Java垃圾回收机制息息相关的类。

  1. 强引用 Strong Reference

    Java中的引用默认就是强引用,任何一个对象的赋值操作就产生了对这个对象的强引用

    Object obj=new Object()
    

    我们new了一个Object对象并将其赋值给obj,这个boj就是new Object()的强引用

    强引用的特征就是只要有强引用存在,被引用的对象就不会被回收(也就是new Object()不会被回收)

  2. 软引用 Soft Reference

    只有在内存不足的情况下,被引用的对象才会被回收

    public class SoftReference<T> extends Reference<T>{public SoftReference(T referent) {/**/}public SoftReference(T referent, ReferenceQueue<? super T> q) {/**/}}
    

    SoftReference继承自Reference,有两种构造函数

    T referent:就是软引用对象

    ReferenceQueue<? super T> q:就是用来存储封装的待回收的Reference对象,eferenceQueue中的对象是由Reference类中的ReferenceHandler内部类进行处理的。

  3. 弱引用 Weak Reference

    弱引用和软引用类似,但是弱引用的对象(即被引用的对象)只要垃圾回收执行不管内存是否充足都会被回收(只有弱引用的时候

  4. 虚引用 Phantom Reference

    虚引用是最弱的引用,引用的是需要被垃圾回收的对象

    虚引用中唯一的作用就是用队列接收对象即将死亡的通知

    所以在类的定义中,get一直返回的都是null

    PhantomReference只有一个构造函数并且必须传入ReferenceQueue

    public class PhantomReference<T> extends Reference<T>{public PhantomReference(T referent, ReferenceQueue<? super T> q){/**/}
    }
    

    ReferenceQueue<? super T> q:就是用来存储封装的待回收的Reference对象。

    虚引用跟踪垃圾回收器(gc)收集对象的活动,在GC的过程中,如果发现有PhantomReference,GC则会将引用放到ReferenceQueue中,由程序员自己处理(这个和软引用是不一样的)

    当程序员调用ReferenceQueue.pull()方法,将引用出ReferenceQueue移除之后,Reference对象会变成Inactive状态,意味着被引用的对象可以被回收了。

3.ThreadLocal为什么会出现内存泄露?

在这里插入图片描述

在当前线程正在运行的时候,如果发生GC,此时ThreadLocal对象没有被其它地方强引用的时候(即只有弱引用),key指向的ThreadLocal的虚引用就会立即断开(因为弱引用指向的对象被垃圾回收了)

这时就会出现ThreadLocalMap中存在key为null的Entry

并且只要当前线程不结束,该ThreadLocalMap对象就会一直存在,无法回收(因为ThreadLocalMap还存在强引用:value本身就存着一个强引用对象)

此时就导致了内存泄露

既然会出现内存泄露为什么Entry的key还要使用弱引用?

为什么要用弱引用呢?

因为假设我们让key强引用ThreadLocal会导致该对象用永远无法gc

如何避免内存泄露?

其实ThreadLocalMap在设计时采取了一些措施来避免这种key为null、value不为null的对象占用内存

具体措施就是在我们调用ThreadLoca的set、get、remove方法时都会将这些key为null的对象清掉,避免因无法回收而导致内存泄露

如果没有及时使用remove方法会导致什么问题?

  1. 假设分配了ThreadLocal对象但是并没有执行get、set、remove方法会导致不能有效地清除null对象

  2. 因为ThreadLocal时属于某个线程的,而在使用线程池的情况下,这些线程都是可重复利用的、存活时间长的线程,因此不及时使用remove方法不仅会导致内存泄露问题,还会引发一些功能逻辑问题

    例如,B请求和A请求分配到了线程池中的同一个线程,那么他们拿到的ThreadLocal可能是一样的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/33508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新版本2023UI千月影视APP源码 开源完美版前后端完美匹配 后端基于ThinkPHP框架

最新版本的2023UI千月影视APP源码是一款开源的完美版应用程序&#xff0c;具备前后端完美匹配的特点。该应用的后端开发基于ThinkPHP框架&#xff0c;这是一个广泛使用的PHP开发框架&#xff0c;具有稳定性和安全性方面的优势。 2023UI千月影视APP是一款提供电影、电视剧、综艺…

ES6 解构

解构的语法 … {} 解构的语法中&#xff0c;...&#xff08;展开运算符&#xff09;和 {}&#xff08;对象字面量&#xff09;扮演着不同的角色。 ...&#xff08;展开运算符&#xff09;&#xff1a; 在解构中&#xff0c;... 被用作展开运算符&#xff0c;用于将数组或对象中…

深入理解MySQL表的操作和管理

MySQL是一种广泛使用的关系型数据库管理系统&#xff0c;用于存储和管理大量结构化数据。在MySQL中&#xff0c;表是数据的基本组织单位&#xff0c;对表的操作和管理能力对于数据库的性能和数据完整性至关重要。本文将深入讨论MySQL表的操作和管理&#xff0c;包括创建表、修改…

Clickhouse学习系列——一条SQL完成gourp by分组与不分组数值计算

笔者在近一两年接触了Clickhouse数据库&#xff0c;在项目中也进行了一些实践&#xff0c;但一直都没有一些技术文章的沉淀&#xff0c;近期打算做个系列&#xff0c;通过一些具体的场景将Clickhouse的用法进行沉淀和分享&#xff0c;供大家参考。 首先我们假设一个Clickhouse数…

智能合约 -- 常规漏洞分析 + 实例

1.重入攻击 漏洞分析 攻击者利用合约漏洞&#xff0c;通过fallback()或者receive()函数进行函数递归进行持续取钱。 刚才试了一下可以递归10次&#xff0c;貌似就结束了(version: 0.8.20)。 直接看代码: 银行合约&#xff1a;有存钱、取钱、查看账户余额等函数。攻击合约:…

第04天 Spring是如何解决循环依赖的

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

【VUE】7、VUE项目中集成watermark实现页面添加水印

在网站浏览中&#xff0c;常常需要网页水印&#xff0c;以便防止用户截图或录屏暴露敏感信息后&#xff0c;方便追踪用户来源。 1、安装 watermark 在 package.json 文件 dependencies 节点增加 watermark-dom 依赖 "watermark-dom": "2.3.0"然后执行命…

Petrel解释二维浅地层数据

Petrel是斯伦贝谢开发的一款地质解释和建模软件&#xff0c;有点像地理信息系统的ArcGIS&#xff0c;主要用于数据分析和展示。它不是用来处理原始数据的&#xff0c;而是集成各种处理后的结果数据进行特征分析和目标拾取。当然&#xff0c;它也能读取原始数据&#xff0c;比如…

Xilinx DDR3学习总结——2、MIG exmaple直接上板

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Xilinx DDR3学习总结——2、MIG exmaple直接上板查看初始化状态 前言修改内容上板 前言 上一篇&#xff0c;我们生成了一个example&#xff0c;example的测试激励看起来都比…

Vue 3.0中的Treeshaking?

1.treeshaking是什么&#xff1f; Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术&#xff0c;专业术语叫 Dead code elimination 简单来讲&#xff0c;就是在保持代码运行结果不变的前提下&#xff0c;去除无用的代码 如果把代码打包比作制作蛋糕&#…

5. 服务发现

当主机较少时&#xff0c;在抓取配置中手动列出它们的IP地址和端口是常见的做法&#xff0c;但不适用于较大规模的集群。尤其不适用使用容器和基于云的实例的动态集群&#xff0c;这些实例经常会变化、创建或销毁的情况。 Prometheus通过使用服务发现解决了这个问题&#xff1…

C# 扩展方法

C# 扩展方法 假设该类是密封的&#xff0c;不能访问代码&#xff0c;或有其他的设计原因使这些方法不能工作&#xff0c;就不得不在另一个类中使用该类的公有可用成员编写一个方法。 假设这个类是密封的&#xff1a; sealed class MyData{double D1;double D2;double D3;publi…

【Mysql】修改definer

修改definer 本文介绍如何修改MySQL中的function、procedure、event、view和trigger的definer 修改function、procedure的definer 首先&#xff0c;我们需要登录MySQL命令行界面&#xff0c;然后执行以下命令&#xff1a; select definer from mysql.proc;这个命令会列出所…

EFLFK——ELK日志分析系统+kafka+filebeat架构(3)

zookeeperkafka分布式消息队列集群的部署 紧接上期&#xff0c;在ELFK的基础上&#xff0c;添加kafka做数据缓冲 附kafka消息队列 nginx服务器配置filebeat收集日志&#xff1a;192.168.116.40&#xff0c;修改配置将采集到的日志转发给kafka&#xff1b; kafka集群&#xff…

(5)所有角色数据分析页面的构建-5

所有角色数据分析页面&#xff0c;包括一个时间轴柱状图、六个散点图、六个柱状图(每个属性角色的生命值/防御力/攻击力的max与min的对比)。 """绘图""" from pyecharts.charts import Timeline from find_type import FindType import pandas …

RN 使用react-navigation写可以滚动的横向导航条(expo项目)

装包&#xff1a; yarn add react-navigation/material-top-tabs react-native-tab-view npx expo install react-native-pager-view import React from react import { View, Text, ScrollView, SafeAreaView } from react-native import { Icon } from ../../../../../compo…

栈和队列详解

目录 栈 栈的概念及结构&#xff1a; 栈的实现&#xff1a; 代码实现&#xff1a; Stack.h stack.c 队列&#xff1a; 概念及结构&#xff1a; 队列的实现&#xff1a; 代码实现&#xff1a; Queue.h Queue.c 拓展&#xff1a; 循环队列&#xff08;LeetCode题目链接&#xff0…

rust里如何快速实现一个LRU 本地缓存?

LRU是Least Recently Used&#xff08;最近最少使用&#xff09;的缩写&#xff0c;是一种常见的缓存淘汰算法。LRU算法的基本思想是&#xff0c;当缓存空间已满时&#xff0c;优先淘汰最近最少使用的数据&#xff0c;以保留最常用的数据。 在计算机系统中&#xff0c;LRU算法…

http历史版本

1&#xff0c;HTTP0.9 最早的http版本&#xff0c;后来才被定义为0.9版本。 这时候通信采用的是纯文本格式&#xff1b; 只支持get请求&#xff0c;且在服务器响应之后就关闭连接&#xff1b; 没有请求头的概念&#xff0c;功能比较简单。 2&#xff0c;HTTP1.0 这个版本增…

C++中new/malloc,delete/free的区别

new和delete是操作符&#xff0c;malloc和free是库函数。 执行new实际上执行了两个操作&#xff1a;1、分配未初始化的内存空间&#xff0c;也就是调用malloc库函数。2、使用对象的构造函数对空间进行初始化&#xff0c;并返回空间的首地址。 如果第一步分配空间出现问题&…