详解ThreadLocal为什么会内存溢出原理

 更新时间:2023年01月04日 14:56:36   作者:Lxlxxx  
这篇文章主要为大家介绍了ThreadLocal为什么会内存溢出原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

关于ThreadLocal (线程本地存储),从字面意思上看主要是存储一些本地变量,使它们能在一个线程内共用,与其他的线程进行数据隔离,保证了数据在一个线程内的安全性,日常的开发中,ThreadLocal的使用场景还是比较常见的,包括登陆信息的token的存储、连接管理一个线程持有一个链接,该连接可以在不同的方法之间进行传递,一个线程内数据共享,通过key,value的形式存储数据。

ThreadLocal源码分析

ThreadLocal类有一个静态内部类,ThreadLocalMap可以看到内部有个Entry 数组k就是ThreadLocal的引用,Entry 继承了WeakReference 说明Entry 的k是个弱引用,从这看来如果是弱引用那么就不会存在内存溢出,GC运行的时候,这个对象就会被回收掉,value则是存储的对象,而ThreadLocalMap则是由threadLocals来创建的,可以看到这两个变量的默认都是NULL。

p>只有当线程第一次调用的时候才会创建它。

ThreadLocal value内存溢出

前面讲到ThreadLocal的key是threadlocals是弱引用不会存在内存溢出,那么容易存在内存溢出的一定是它的value,它与current thread 存在一个强引用的关系,导致value无法进行回收,如果线程的对象一直不去销毁这个强引用的对象,那么导致这个关系一直存在就会出现内存溢出,

/**
 * 内存溢出例子
 */
public class ThreadLocalTest {
    static class Mytask{
        //定义10m的Byte数组
       private Byte[] bytes =new Byte[10 *1024 * 1024];
    }
    private static ThreadLocal<Mytask> threadLocal = new ThreadLocal();
    public static void main(String[] args) throws InterruptedException {
        // 5个核心线程、5个最大线程、队列长度100
        ThreadPoolExecutor threadPoolExecutor =new ThreadPoolExecutor(5, 5, 60,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
        for (int i = 0; i < 10; i++) {
            //执行任务
            executeTask(threadPoolExecutor);
            Thread.sleep(1000);
        }
    }
    private static void executeTask(ThreadPoolExecutor threadPoolExecutor){
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("创建Mytask对象");
                Mytask mytask =new Mytask();
                threadLocal.set(mytask);
            }
        });
    }

堆内存设置50m

通过上面代码,创建线程池对创建的任务,放入threadlocal里面,可以看到出现了堆内存的溢出,存放的任务一直在引用没有得到释放导致堆内存空间不足。

p>我们在set值到threadLocal后面加入finally,调用它的remove方法来清除它的内存那么就不会发生内存溢出。

来看看remove的代码,可以看到获取当前线程的threadLocals,然后调用remove方法获取到全部的Entry数组,判断不为空,key也是当前的key则调用clear方法将数组清除,这样数组空间得到了释放自然就不会出现内存溢出。

public void remove() {
    ThreadLocalMap m = getMap(Thread./currentThread/());
    if (m != null)
        m.remove(this);
}
private void remove(ThreadLocal<?> key) {
    Entry[] tab = table;
    int len = tab.length;
    int i = key.threadLocalHashCode & (len-1);
    for (Entry e = tab[i];
         e != null;
         e = tab[i = nextIndex(i, len)]) {
        if (e.get() == key) {
            e.clear();
            expungeStaleEntry(i);
            return;
        }
    }
}

总结

ThreadLocal在使用的时候一定到进行remove,这也是一个比较常见的内存溢出的例子,希望大家引以为戒。

以上就是详解ThreadLocal为什么会内存溢出原理的详细内容,更多关于ThreadLocal内存溢出的资料请关注脚本之家其它相关文章!

相关文章

  • java中 ${} 和 #{} 有什么区别

    java中 ${} 和 #{} 有什么区别

    本文主要介绍了java中${}和#{}有什么区别,${}和#{}都是MyBatis中用来替换参数的,它们都可以将用户传递过来的参数,替换到MyBatis最终生成的SQL中,但它们区别却是很大的,感兴趣的小伙伴可以一起来学习下面详细内容
    2022-08-08
  • 浅谈Spring bean 生命周期验证

    浅谈Spring bean 生命周期验证

    本篇文章主要介绍了浅谈Spring bean 生命周期验证,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java国际化简介_动力节点Java学院整理

    Java国际化简介_动力节点Java学院整理

    这篇文章主要为大家简单介绍了Java国际化的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Java Unsafe学习笔记分享

    Java Unsafe学习笔记分享

    今天小编就为大家分享一篇Java Unsafe学习笔记,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • java多线程Synchronized实现可见性原理解析

    java多线程Synchronized实现可见性原理解析

    这篇文章主要介绍了java多线程Synchronized实现可见性原理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • 剑指Offer之Java算法习题精讲二叉树专题篇下

    剑指Offer之Java算法习题精讲二叉树专题篇下

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • java计算两个日期中间的时间

    java计算两个日期中间的时间

    这篇文章主要介绍了java计算两个日期中间的时间的相关资料,需要的朋友可以参考下
    2017-04-04
  • 解决JSON.toJSONString首字母大小写的问题

    解决JSON.toJSONString首字母大小写的问题

    这篇文章主要介绍了解决JSON.toJSONString首字母大小写的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • java基本教程之线程休眠 java多线程教程

    java基本教程之线程休眠 java多线程教程

    本文对javaThread中sleep()方法进行介绍,sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”,大家参考使用吧
    2014-01-01
  • java实现简单的客户信息管理系统

    java实现简单的客户信息管理系统

    这篇文章主要为大家详细介绍了java实现简单的客户信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06

最新评论