iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >ThreadLocal导致JVM内存泄漏原因探究
  • 909
分享到

ThreadLocal导致JVM内存泄漏原因探究

JVM内存泄漏JVMThreadLocal内存泄漏 2023-05-16 17:05:51 909人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录为什么要使用ThreadLocal使用ThreadLocal具体实现引发内存泄漏的原因为什么要使用ThreadLocal 在一整个业务逻辑流程中,为了在不同的地方或者不同的方法中

为什么要使用ThreadLocal

在一整个业务逻辑流程中,为了在不同的地方或者不同的方法中使用同一个对象,但是又不想在方法形参中加这个对象,那么就可以使用ThreadLocal来保存

ThreadLocal最大的应用场景就是跨方法进行参数传递

ThreadLocal可以给每一个线程绑定一个变量的副本

使用ThreadLocal

ThreadLocal常用的方法其实也就下面几个

// 返回当前线程所对应的线程局部变量。
public T get() {}
// 设置当前线程的线程局部变量的值。
public void set(T value) {}
// 移除,当线程结束后,该线程thread对象中的局部变量将在下一次GC时回收,如果显示的调用此方法只是可以加快内存回收的速度
// 所以javase开发 普通new Thread()方式中,这个方法并不是必须要调用的
// 但是javaweb开发中就必须显示调用,因为javaweb都是使用的线程池,并不是一个客户端来一个请求,thread线程对象用完就删除,而是会放回线程池中。
public void remove() {}
// 返回该线程局部变量的一个初始化
// protected方法,显然是为了让子类覆盖而设计的。这个方法在第一次调用 get()或 set(Object)时才执行,并且仅执行 1 次
protected T initialValue() {}

在具体使用的时候,我们ThreadLocal对象一定会定义成静态的,如果不定义成静态的那么其他地方如何通过这个ThreadLocal实例去Map中拿数据嘞?

而且如果是多个线程保存一个变量的副本,一个静态的ThreadLocal也足够了,因为它是作为多个map中的key存在的

简单使用案例


public class UseThreadLocalTest {
    public static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public static class ThreadTest extends Thread{
        private Integer id;
        ThreadTest(Integer id){
            this.id = id;
        }
        @Override
        public void run() {
            threadLocal.set(Thread.currentThread().getName() + ":" + id);
            print();
        }
        public void print(){
            System.out.println(threadLocal.get());
        }
    }
    
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new ThreadTest(i).start();
        }
    }
}

// 输入结果如下
Thread-0:0
Thread-1:1
Thread-2:2

具体实现

ThreadLocal底层set()和get()方法的源码如下

// 存值时 map最终是存储在当前线程Thread t = Thread.currentThread()中的,是thread的一个成员变量
// map的key是当前threadLocal对象实例,value是要存的值
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
// 取值时也是也是先从当前线程Thread对象中取出map
// 然后在从map中根据当前threadLocal对象实例作为key获取到entry对象
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

为了提高性能,才没有采用加的方式,而是将map和各个线程thread对象进行关联,这样就避免了产生线程安全问题,也避免了加锁,提高了性能

我们接下来再来看看ThreadLocalMap它的实现,它类似于jdk1.7版本的HashMap,底层存储的是一个Entry对象的数组,初始容量也是16,存值时先用hash结果和数组长度取余得到数组下标位置,然后判断是否产生了hash冲突,然后使用开发定址法来处理。根据算法的不同又可以分为线性探测再散列、二次探测再散列、伪随机探测再散列。ThreadLocalMap它是使用的线性探测再散列法,如下所示

private static int nextIndex(int i, int len) {
    return ((i + 1 < len) ? i + 1 : 0);
}

Entry对象中的key它是一个弱引用,Entry继承了WeakReference类,弱引用跟没引用差不多,GC会直接回收掉,不管内存是否足够都会回收

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

引发内存泄漏的原因

上面再介绍ThreadLocal基本使用api方法的时候也提到了,如果只是创建一个普通的线程Thread对象,是不会产生内存泄漏问题的。因为map是存储在Thread对象中,一个普通线程执行完了,那么这个线程的局部变量也就会被gc回收。

但如果结合到了线程池,一个Thread线程对象用完后放回线程池中,如果这个时候我们程序不显示的调用remove()方法,那么就会造成内存泄漏问题了。

因为Entry对象中的Key的弱引用,但是value还会存在,就会存在map中key为null的value

ThreadLocal 的底层实现中我们可以看见,无论是 get()set()在某些时 候,调用了 expungeStaleEntry() 方法用来清除 Entry 中 Key 为 null 的 Value,但是这是不及时的,也不是每次都会执行的,所以一些情况下还是会发生内存泄露。

到此这篇关于ThreadLocal导致JVM内存泄漏原因探究的文章就介绍到这了,更多相关JVM内存泄漏内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: ThreadLocal导致JVM内存泄漏原因探究

本文链接: https://www.lsjlt.com/news/210312.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • ThreadLocal导致JVM内存泄漏原因探究
    目录为什么要使用ThreadLocal使用ThreadLocal具体实现引发内存泄漏的原因为什么要使用ThreadLocal 在一整个业务逻辑流程中,为了在不同的地方或者不同的方法中...
    99+
    2023-05-16
    JVM内存泄漏 JVM ThreadLocal内存泄漏
  • Android内存泄漏导致原因深入探究
    目录什么是内存泄露哪些操作会造成内存泄漏常见内存泄露问题1.资源性对象未关闭2.注册对象未注销3.非静态内部类的静态实例4.单例模式引起的内存泄露5.Handler临时性内存泄露6....
    99+
    2023-02-17
    Android内存泄漏原因 Android内存泄漏几种情况
  • Android内存泄漏导致的原因有哪些
    这篇文章主要介绍“Android内存泄漏导致的原因有哪些”,在日常操作中,相信很多人在Android内存泄漏导致的原因有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android内存泄漏导致的原因有哪些...
    99+
    2023-07-05
  • Java中ThreadLocal 导致内存 OOM 的原因分析
    目录原因分析正确的使用方式原因分析 ThreadLocal 导致内存 OOM 的原因是什么? ThreadLocal 底层通过 ThreadLocalMap 存储数据 源码如下:&n...
    99+
    2024-04-02
  • OpenCL clCreateContextFromType函数导致内存泄漏
    内存泄漏是一种资源管理问题,可能会导致程序运行时消耗大量的内存而无法释放。在OpenCL中,clCreateContextFromT...
    99+
    2023-09-26
    内存泄漏
  • Java中ThreadLocal导致内存OOM的原因是什么
    本篇内容介绍了“Java中ThreadLocal导致内存OOM的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!原因分析Thread...
    99+
    2023-06-30
  • JVM内存泄露的原因是什么
    本篇内容介绍了“JVM内存泄露的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 OOM的现象之一今天介绍第一种Java heap...
    99+
    2023-06-02
  • javascript内存泄漏有哪些原因
    本篇内容介绍了“javascript内存泄漏有哪些原因”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • JavaScript中的内存泄漏的原因
    目录前言内存泄漏的场景全局变量闭包DOM元素引用总结前言 JavaScript的内存泄漏指的是一些不再需要的对象仍然占用着内存,导致内存使用量持续增加,甚至造成浏览器崩溃或性能下降。...
    99+
    2023-05-18
    JavaScript 内存泄漏
  • GoLang内存泄漏原因排查详解
    目录背景临时性内存泄漏通道理解背景 Go 语言中有对应的Go 内存回收机制,在Go采用 并发三色标记清除  算法, 但是由于实际的过程中 发现会有一些内存泄漏的常见,内存泄...
    99+
    2022-12-15
    GoLang内存泄漏 Go内存泄漏
  • Java中什么情况会导致内存泄漏
    这篇文章主要讲解了“Java中什么情况会导致内存泄漏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中什么情况会导致内存泄漏”吧!概念内存泄露:指程序中动态分配内存给一些临时对象,但对...
    99+
    2023-06-16
  • golang内存泄漏的原因是什么
    这篇“golang内存泄漏的原因是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“golang内存泄漏的原因是什么”文章吧...
    99+
    2023-07-04
  • Android内存泄漏的原因有哪些
    Android内存泄漏的原因有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在Android开发中,最容易引发的内存泄漏问题的是Context。比如Activity的Con...
    99+
    2023-06-17
  • python内存泄漏的原因有哪些
    Python内存泄漏的原因有以下几个:1. 循环引用:当两个或多个对象相互引用时,如果没有妥善地处理,可能会导致内存泄漏。垃圾回收器...
    99+
    2023-09-15
    python
  • java内存泄漏和内存溢出的原因是什么
    Java内存泄漏和内存溢出的原因如下:1. 内存泄漏:内存泄漏指的是在程序运行过程中,无用的对象仍然被保持在内存中,导致内存占用不断...
    99+
    2023-08-26
    java
  • 内存泄露导致Android 中setVisibility() 失效原理
    目录一、前情概要二、摸索过程1、代码执行了吗?2、视图不显示的直接原因是什么?3、操作的视图是同一个吗?三、解决方案一、前情概要 目前,我在开发的一个 Android 项目需要各个功...
    99+
    2024-04-02
  • JavaScript中出现内存泄漏的原因是什么
    本篇文章给大家分享的是有关JavaScript中出现内存泄漏的原因是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。泄露方式在接下来的内容中...
    99+
    2024-04-02
  • golang容易导致内存泄漏的6种情况汇总
    目录1. 定时器使用不当1.1 time.After()的使用1.2 time.NewTicker资源未及时释放2. select阻塞2.1 导致goroutine阻塞的情况2.2 ...
    99+
    2023-01-09
    golang内存泄漏例子 go 内存泄漏 golang内存泄漏场景
  • Node.js中出现内存泄漏的原因有哪些
    本篇文章给大家分享的是有关Node.js中出现内存泄漏的原因有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。内存泄漏(Memory  Leak)指由于疏忽或错误造...
    99+
    2023-06-17
  • 【MYSQL】mysql5.7-bug -information_schema的表被查询可能导致内存泄漏
    [11 May 2017 6:57] Cho-Shing Ma Description: ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作