首页 > 其他分享 >ThreadLocal 详解【并发容器】

ThreadLocal 详解【并发容器】

时间:2023-05-31 20:56:55浏览次数:41  
标签:num Thread 局部变量 并发 ThreadLocal 详解 线程 内存

ThreadLocal 是什么?有哪些使用场景?

ThreadLocal 是一个本地线程副本变量工具类,在每个线程中都创建了一个ThreadLocalMap 对象,简单说

ThreadLocal 就是一种以空间换时间的做法,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方式,避免资源在多线程间共享。

原理:线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。 Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放, Java 应用就存在内存泄露的风险

经典的使用场景是为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B 线程正在使用的 Connection;还有 Session 管理 等问题。

ThreadLocal 使用例子:

 1 public class TestThreadLocal {
 2 
 3     //线程本地存储变量
 4     private static final ThreadLocal<Integer> THREAD_LOCAL_NUM
 5         = new ThreadLocal<Integer>() {
 6         @Override
 7         protected Integer initialValue() {
 8             return 0;
 9         }
10     };
11     public static void main(String[] args) {
12         for (int i = 0; i <3; i++) {//启动三个线程
13             Thread t = new Thread() {
14                 @Override
15                 public void run() {
16                     add10ByThreadLocal();
17                 }
18             };
19             t.start();
20         }
21     }
22     /**
23     * 线程本地存储变量加 5
24     */
25     private static void add10ByThreadLocal() {
26         for (int i = 0; i <5; i++) {
27             Integer n = THREAD_LOCAL_NUM.get();
28             n += 1;
29             THREAD_LOCAL_NUM.set(n);
30             System.out.println(Thread.currentThread().getName() + " :
31             ThreadLocal num=" + n);
32         }
33     }
34 }            

打印结果:启动了 3 个线程,每个线程最后都打印到 “ThreadLocal

num=5” ,而不是 num 一直在累加直到值等于 15

 1 Thread-0 : ThreadLocal num=1
 2 Thread-1 : ThreadLocal num=1
 3 Thread-0 : ThreadLocal num=2
 4 Thread-0 : ThreadLocal num=3
 5 Thread-1 : ThreadLocal num=2
 6 Thread-2 : ThreadLocal num=1
 7 Thread-0 : ThreadLocal num=4
 8 Thread-2 : ThreadLocal num=2
 9 Thread-1 : ThreadLocal num=3
10 Thread-1 : ThreadLocal num=4
11 Thread-2 : ThreadLocal num=3
12 Thread-0 : ThreadLocal num=5
13 Thread-2 : ThreadLocal num=4
14 Thread-2 : ThreadLocal num=5
15 Thread-1 : ThreadLocal num=5

什么是线程局部变量?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。 Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器) 使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放, Java 应用就存在内存泄露的风险。

 

ThreadLocal 内存泄漏分析与解决方案

ThreadLocal 造成内存泄漏的原因?

ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候, key 会被清理掉,而 value 不会被清理掉。这样一来,ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话, value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。ThreadLocalMap 实现中已经考虑了这种情况,在调用 set()、 get()、remove() 方法的时候,会清理掉 key 为 null 的记录。使用完 ThreadLocal 方法后 最好手动调用 remove() 方法。

ThreadLocal 内存泄漏解决方案?

• 每次使用完 ThreadLocal,都调用它的 remove()方法,清除数据。

• 在使用线程池的情况下,没有及时清理 ThreadLocal,不仅是内存泄漏的问题,更严重的是可能导致业务逻辑出现问题。所以,使用 ThreadLocal就跟加锁完要解锁一样,用完就清理。

标签:num,Thread,局部变量,并发,ThreadLocal,详解,线程,内存
From: https://www.cnblogs.com/Rover20230226/p/17447294.html

相关文章

  • 树状数组详解
    先来看几个问题吧。1.什么是树状数组?顾名思义,就是用数组来模拟树形结构呗。那么衍生出一个问题,为什么不直接建树?答案是没必要,因为树状数组能处理的问题就没必要建树。和Trie树的构造方式有类似之处。2.树状数组可以解决什么问题可以解决大部分基于区间上的更新以及求和问题。......
  • LVS原理详解以及部署
    linuxvirtualserver简称LVS,Internet的快速增长使多媒体网络服务器面对的访问数量快速增加,服务器需要具备提供大量并发访问服务的能力,因此对于大负载的服务器来讲,CPU、I/O处理能力很快会成为瓶颈。由于单台服务器的性能总是有限的,简单的提高硬件性能并不能真正解决这个问题。为......
  • Kohl's百货的EDI需求详解
    Kohl's是一家美国的连锁百货公司,成立于1962年,总部位于美国威斯康星州的门多西。该公司经营各种商品,包括服装、鞋子、家居用品、电子产品、化妆品等,并拥有超过1,100家门店,分布在美国各地。本文将为大家介绍Kohl's的EDI需求。Kohl'sEDI需求EDI传输协议:AS2EDI报文标准:X12EDI......
  • C++四种强制类型详解
    向上转型(上行转换)派生类对象转换为基类对象(包括指针和对象),直接转换由编译器完成,是绝对安全的内存里面:基类对象相当于只是换了个地址,换成了派生类中存储基类成员的内存地址,但是派生类对象中有的,基类没有的变量仍然存在内存中(保留了再次从基类转换成派生类的可能性)向下转型(下行......
  • StampedLock:高并发场景下一种比读写锁更快的锁
    摘要:在读多写少的环境中,有没有一种比ReadWriteLock更快的锁呢?有,那就是JDK1.8中新增的StampedLock!本文分享自华为云社区《【高并发】高并发场景下一种比读写锁更快的锁》,作者:冰河。什么是StampedLock?ReadWriteLock锁允许多个线程同时读取共享变量,但是在读取共享变量的时候,不......
  • Golang扫盲式学习——GO并发 | (一)
    并发与并行......
  • C++多态虚函数表详解(多重继承、多继承情况)
    本文关键词:C++多态多继承多重继承虚函数表虚函数指针动态绑定概述:C++相对其他面向对象语言来说,之所以灵活、高效。很大程度的占比在于其多态技术和模板技术。C++虚函数表是支撑C++多态的重要技术,它是C++动态绑定技术的核心。本文章将着重图解虚函数表相关知识,在阅读本文......
  • 10.UG钣金使用方法详解
    1.创建钣金件或者拉伸后转换为钣金2.    ......
  • BIO、NIO、AIO区别详解
    BIO:同步阻塞主线程发起io请求后,需要等待当前io操作完成,才能继续执行。NIO:同步非阻塞引入selector、channel、等概念,当主线程发起io请求后,轮询的查看系统是否准备好执行io操作,没有准备好则主线程不会阻塞会继续执行,准备好主线程会阻塞等待io操作完成。AIO:异步非阻塞主线程发起......
  • redis 7.0 配置文件详解
    本文配置文件版本是Redis7.0。5.5.1常规通用配置这些是我的常规配置,每个Redis启动必备参数,你一定要掌握,涉及到网络、模块插件、运行模式、日志等。MODULES这个配置可以加载模块插件增强我的功能,常见的模块有RedisSearch、RedisBloom等。关于模块加载可以参考【5.6布隆......