首页 > 其他分享 >ThreadLocal的作用以及其存在的问题

ThreadLocal的作用以及其存在的问题

时间:2023-08-18 20:11:21浏览次数:48  
标签:map 存在 Thread ThreadLocalMap value ThreadLocal 线程 作用

ThreadLocal是JDK自带的一个类,他的作用是为每个线程中创建专属本地变量,这些变量只能被当前线程访问和修改,其他线程无法访问,当你创建了一个ThreadLocal里的变量后,每个访问这个变量的线程都会获得一个此变量的本地副本,同时THreadLocal提供了get()、set()方法来获取默认值,或将其值更改为当前线程所存的副本的值。   在ThreadLocal的源码中可以发现,其set()方法实际上是通过Thread.currentThread()方法获取当前的线程,再通过getMap获得当前线程的ThreadLocalMap对象,对该对象进行if/else判断,判断这个map是否为空,如果不为空,就往ThreadLocalMap中加入一个键值对,键是ThreadLocal对象,值则是set方法中传入的想要在该线程中存储来进行共享的变量副本,如果为空,那就创建一个新的ThreadLocal对象,并将其存储到该Map中。   get()方法与set()方法前面一样,都是获得当前线程的ThreadLocalMap对象,再对map是否为空其进行判断,如果不为空:1、获取其当前ThreadLocal的键值对对象;2、对获取到的键值对对象进行非空判断,不为空则将键值对的值返回出去,为空则不做处理;如果为空,那么不进入if中,调用setInitialValue()方法来获取初始值,并将其设置为当前线程的变量副本。  

    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();
    }

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

ThreadLocal很有用,但是也存在一些问题,1、内存泄露问题,由于ThreadLocalMap中使用的key是弱引用,而value是强引用,所以如果ThreadLocal没有被外部强引用的时候,如果发生垃圾回收,key会被清理掉,而value不会被清理掉,一旦发生,ThreadlocalMap中就会出现一个key为null的键值对,如果不做处理,value就永远无法被回收,就会产生内存泄漏;2、如果线程数量非常庞大,ThreadlocalMap的查询效率可能会降低,可以考虑使用线程池来控制线程的创建和销毁,来减少ThreadlocalMap的大小,但是如果使用线程池复用线程时没有清除ThreadLocal变量,可能会导致线程之间共享ThreadLocal变量;为了解决以上问题,ThreadlocalMap也提供了一个remove()方法,会清理掉key为null的记录,建议在通过try/catch/finally中的finally代码块来调用remove(),确保其一定会执行。

 

     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null) {
             m.remove(this);
         }
     }

 

标签:map,存在,Thread,ThreadLocalMap,value,ThreadLocal,线程,作用
From: https://www.cnblogs.com/hwj7/p/17641503.html

相关文章

  • AI聊天机器人原来有这么多作用
    AI聊天机器人是一种能够模拟人类对话并利用人工智能技术进行自主学习和适应的计算机程序。它们能够根据用户的输入内容来分析用户的需求,并提供相应的回答和建议。今天looklook就来和大家详细讲一下AI聊天机器人到底有什么作用吧。AI聊天机器人的作用1、客户服务:AI聊天机器人可以作......
  • 《Javascript中关于this作用域的箭头函数,普通函数以及回调函数中的特殊作用》
    开言这篇文章的内容很简单,一句话就是“涉及this指向谁”!!!但是涉及JavaScript的普通函数,箭头函数,WIndow,回调,Object等各种知识点其糅杂在一起,其知识点会很混乱,我们要理性头绪!!简单来说,普通函数可以看做管理严格的孩子,箭头函数是一个自由自在的孩子因此,在object中,使用箭头函数很危......
  • C++快速入门 第四十二讲:链接和作用域
    与作用域有关的另一个概念是链接,当同时编译多个文件时,每个源文件被称为一个翻译单元,在某一个翻译单元里定义的东西在另一个翻译单元里使用正是链接发挥作用的地方。存储类(storageclass):每个变量都有一个存储类,它决定着程序将把变量的值储存在计算机的什么地方、如何存储、以及变......
  • C++快速入门 第四十三讲:链接和作用域2
    1header.h文件23#ifndefHEADER_H4#defineHEADER_H56unsignedlongreturnFactorial(unsignedshortnum);7staticconstunsignedshortheaderNum=5;//定义静态恒定值的全局变量89#endif1011that.cpp文件:1213#include"header.h"14uns......
  • (Repository)仓储的使用与作用(一)
    仓储(Respository)是存在于工作单元和数据库之间单独分离出来的一层,是对数据访问的封装。其优点:1)业务层不需要知道它的具体实现,达到了分离关注点。2)提高了对数据库访问的维护,对于仓储的改变并不会改变业务的逻辑,数据库可以用SqlServer,MySql等。 domain(领域......
  • 移除重新引用dll不起作用,依然是有黄色的感叹号
    记录下今天遇到的一个很奇怪的问题:移除重新引用dll不起作用,依然是有黄色的感叹号深入的原因未知,我是将项目拷贝了一下,重新生成出现的问题。解决办法就是只用最原始的项目。从svn,到本地,全部都改为了同一个正常的项目,放弃拷贝这一方法。......
  • 三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析
    三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析  在移动设备上,大规模场景的加载和渲染是一个不容忽视的问题。对于OSGB格式轻量化处理来说,大规模场景的加载和渲染也是其中一项重要的任务。本文将重点分析OSGB格式轻量化处理在大规模场景的加载和渲染中发挥......
  • #yyds干货盘点# LeetCode程序员面试金典:存在重复元素 II
    题目:给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i]==nums[j] 且 abs(i-j)<=k 。如果存在,返回 true ;否则,返回 false 。 示例 1:输入:nums=[1,2,3,1],k=3输出:true示例2:输入:nums=[1,0,1,1],k=1输出......
  • 浅谈城市智慧水务建设存在的问题及改进措施
    未晓妃安科瑞电气股份有限公司上海嘉定201801摘要:随着城市化进程的推进,城市水资源管理逐漸提高。智慧城市建设已成为现代化城市建设的重要部分。智慧水务建设具有水资源调整功能,可以帮助水资源管理及时采取纠正措施,避免灾害的发生。文章针对城市智慧水务建设中的问题,提出了改进措......
  • 数据库连接池为什么要用threadlocal呢?不用会怎样?
    数据库连接池使用ThreadLocal的主要原因是为了保证每个线程都有其独立的数据库连接,这样可以避免多个线程之间的连接干扰,提高系统的稳定性和性能。为什么使用ThreadLocal?线程安全:ThreadLocal可以为每个线程提供一个独立的数据库连接,确保多个线程操作数据库时不会出现资源竞争的......