首页 > 其他分享 >线程-ThreadLocal篇

线程-ThreadLocal篇

时间:2023-11-24 23:34:16浏览次数:29  
标签:Thread ThreadLocalMap ThreadLocal 线程 内存 key

ThreadLocal类(用于创建一个线程本地变量)

在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。

ThreadLocal的使用场景:

数据库连接:

1.在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。
2.ThreadLocal不是一个线程而是一个线程的本地化对象。当工作于多线程环境中的对象采用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的副本。每个线程都可以独立的改变自己的副本,而不影响其他线程的副本。

内存泄露问题

概念:ThreadLocal被回收了,ThreadLocalMap Entry的key没有了指向,但Entry仍然有ThreadRef->Thread->ThreadLoalMap-> Entry value-> Object 这条引用一直存在导致内存泄露。

概率比较低,原因:

首先ThreadLocal被两种引用指向

1.ThreadLocalRef->ThreadLocal(强引用)

2.ThreadLocalMap Entry key ->ThreadLocal(弱引用)

只要ThreadLocal没被回收(使用时强引用不置null),那ThreadLocalMap Entry key的指向就不会在GC时断开被回收,也没有内存泄露一说法;通过ThreadLocal了解实现后,又知道ThreadLocalMap是依附在Thread上的,只要Thread销毁,那ThreadLocalMap也会销毁;所以非线程池环境下,也不会有长期性的内存泄露问题;而ThreadLocal实现下还做了些”保护“措施,如果在操作ThreadLocal时,发现key为null,会将其清除掉;所以,如果在线程池(线程复用)环境下,如果还会调用ThreadLocal的set/get/remove方法,发现key为null会进行清除,不会有长期性的内存泄露问题。

总结:那存在长期性内存泄露需要满足条件:ThreadLocal被回收&&线程被复用&&线程复用后不再调用ThreadLocal的set/get/remove方法,所以概率是非常低的。

为什么要将ThreadLocalMap的key设置为弱引用:

外界是通过ThreadLocal来对ThreadLocalMap进行操作的,假设外界使用ThreadLocal的对象被置null了,ThreadLocalMap的强引用指向ThreadLocal也毫无意义。弱引用反而可以预防大多数内存泄漏的情况。毕竟被回收后,下一次调用set/get/remove时ThreadLocal内部会清除掉。

为什么建议把ThreadLocal修饰为static

ThreadLocal能实现了线程的数据隔离,不在于它自己本身,而在于Thread的ThreadLocalMap。所以,ThreadLocal可以只初始化一次,只分配一块存储空间就足以了,没必要作为成员变量多次被初始化。

 

标签:Thread,ThreadLocalMap,ThreadLocal,线程,内存,key
From: https://www.cnblogs.com/nxjblog/p/17855025.html

相关文章

  • Java21虚拟线程实践
    Java21虚拟线程实践一个月之前,java21正式版发布了,作为继java17之后的又一个长期支持版本(LTS),为我们带来了很多新的特性,其中我最感兴趣的就是虚拟线程(virtualthread),相信大家对虚拟线程也很好奇。趁着空闲时间安装了jdk21来体验一把,顺便把我查到的关于java21虚拟线程相关的资料......
  • 多线程
    多线程线程其实是程序中的一条执行路径我之前所以写的程序,其实都是单线程程序那么怎样的程序才是多线程程序呢?支持同时有很多人一起进入网站,并且每一个人的行为互不影响。例如百度网盘中,可以同时上传或者下载的多个文件,这些程序中其实就有多条执行路径,每一个执行路径就是一条......
  • C++11 多线程并发 互斥量、条件变量和信号量
    互斥量Classesmutex(C++11)providesbasicmutualexclusionfacility(class)timed_mutex(C++11)providesmutualexclusionfacilitywhichimplementslockingwithatimeout(class)recursive_mutex(C++11)providesmutualexclusionfacili......
  • 【Python进阶笔记】md文档笔记第6篇:Python进程和多线程使用(图文和代码)
    本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。全套md格式笔记和代码自取:请移步这里......
  • java多线程学习之路-不能理解
    1importjava.util.concurrent.CountDownLatch;23/**4*颠覆理解的,为什么不会出问题,执行多次,结果都是正确,并且一致5*/6classMyData{7inta=5;//可预定总座位数8intb=0;//已预定座位数910publicvoidyd(){11if(b<......
  • 手写线程池——C和C++版本
    内容参考:爱编程的大丙(subingwen.cn)C语言版大致思路采用生产者——消费者模型:生产者:用户向任务队列添加任务,是生产者。消费者:线程池里面的线程从任务队列中取出任务是,是消费者。任务队列:单个任务结构:使用结构体封装,其中包含一个函数指针,用于指向要处理的具体任务......
  • C++11 多线程(std::thread)实例
    C++11的std::thread在C中已经有一个叫做pthread的东西来进行多线程编程,但是并不好用(如果你认为句柄、回调式编程很实用,那请当我没说),所以c++11标准库中出现了一个叫作std::thread的东西。std::thread常用成员函数构造&析构函数举个栗子例一:thread的基本使用1//Compiler:......
  • Java线程生命周期
    操作系统线程生命周期操作系统线程生命状态有5种。初始状态(New)进程正在被创建时的状态。仅为线程对象开辟了一块堆内存,实际上线程在操作系统层面还未创建。就绪状态(Ready)可运行,由于其他进程处于运行状态而暂时停止运行运行状态(Running)该进程此时正占用CPU......
  • Android新手必学:关于多线程的知识
    引言在Android开发中,多线程编程是一项非常重要的技能。Android应用程序通常需要同时执行多个任务,如网络请求、文件读写、耗时计算等。如果在主线程中执行这些任务,会导致应用程序的界面卡顿,用户体验变差。因此,我们需要使用多线程来实现并发执行任务,提高应用程序的响应性能和用户体验......
  • 线程池-常见问题
    尽管线程池对于构建多线程应用是个很强大的机制,但它也不是没有缺点的。使用线程池构建的应用会面临其他多线程应用所面对的一样的并发风险,比如同步错误和死锁,此外线程池还有其他的一些特有缺陷,比如线程池-关联死锁,资源不足,还有线程泄漏。 死锁任何多线程应用都会面临死锁的......