返回顶部
首页 > 资讯 > 后端开发 > JAVA >【Java】线程数据共享和安全 -ThreadLocal
  • 440
分享到

【Java】线程数据共享和安全 -ThreadLocal

java开发语言ThreadLocalservlettomcatjavascript 2023-09-08 13:09:44 440人浏览 独家记忆
摘要

 🎄欢迎来到@边境矢梦°的csdn博文🎄  🎄本文主要梳理线程数据共享和安全 -ThreadLocal🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做

 🎄欢迎来到@边境矢梦°的csdn博文🎄

 🎄本文主要梳理线程数据共享和安全 -ThreadLocal🎄


🌈我是边境矢梦°,一个正在为秋招算法竞赛做准备的学生🌈
🎆喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路🎆

Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒🌓🌔🌕    

在这里插入图片描述

目录

🎉 Java的有利武器:ThreadLocal 

🚀 第一章 - 什么是ThreadLocal?

📝第二章 - ThreadLocal原理

  📌源码分析

📜 第三章 - 如何使用ThreadLocal

🌟 第四章 - ThreadLocal的应用场景

🔮总结


🎉 Java的有利武器:ThreadLocal 🎉

📣今天我要为大家推荐一个Java中非常实用且神奇的工具——ThreadLocal。它可以让我们在多线程环境下,轻松地实现线程私有的数据存储。它可以帮助我们在多线程环境下轻松解决变量共享和线程安全的问题。🔍


🚀 第一章 - 什么是ThreadLocal?

1. ThreadLocal 的作用,可以实现在同一个线程数据共享 , 从而解决多线程数据安全问题 . 2. ThreadLocal 可以给当前线程关联一个数据 ( 普通变量、对象、数组 )set 方法 [ 源码 !] 3. ThreadLocal 可以像 Map 一样存取数据, key 为当前线程 , get 方法 4. 每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数 据,就需要使用多个 ThreadLocal 对象实例 5. 每个 ThreadLocal 对象实例定义的时候,一般为 static 类型 6. ThreadLocal 中保存数据,在线程销毁后,会自动释放

📷 图一:ThreadLocal示意图


📝第二章 - ThreadLocal原理

⚠️一个ThreadLocal可以同时给多个线程分别关联各自的数据。每个线程在访问ThreadLocal时,都会获取到自己独立的数据副本,互不干扰。这就是ThreadLocal的独立性和隔离性所表现出来的特点。

📷 图二:ThreadLocal同时给多个线程分别关联各自的数据示意图

⚠️ThreadLocal是用于实现线程局部变量的机制,它为每个线程提供了一个独立的副本,保证了线程的隔离性。因此,一个ThreadLocal变量最多只能关联一个线程的数据。

📷 图三:ThreadLocal一个线程一个数据示意图


  📌源码分析

实际上,ThreadLocal本身并没有存储任何对象,所有的东西都存储在Thread对象本身里!

首先,在Thread对象(注意,不是ThreadLocal!)里有个成员变量:

ThreadLocal.ThreadLocalMap threadLocals = null;

这个成员变量的类型是ThreadLocal.ThreadLocalMap,这是ThreadLocal的一个内部类,可以理解为一个简单的HashMap(关于这个内部类的实现本篇就不详细展开了,有兴趣的同学可以看源码),就是保存键值对的一个容器

其实,所有set到ThreadLocal上的对象,实际都保存在当前Thread中的threadLocals成员变量里。

为了说的清楚,下面我用伪代码的形式,写一下ThreadLocal的Set()方法的核心逻辑:

public void set(T value) {        Thread t = Thread.currentThread(); //先获得当前线程        if (t.threadLocals != null){ //判断当前线程上的threadLocals成员是否为空            t.threadLocals.set(this, value); //如果threadLocals不等于空,则set value,ThreadLocal对象作为key值。        }else{            t.threadLocals = new ThreadLocalMap(); //如果threadLocals为空,则创建之然后再set value。            t.threadLocals.set(this, value);         }    }

通过以上代码大家应该都能看清楚,真正的value值是保存在Thread对象上的,同时,key值是ThreadLocal对象。

再看看get方法,依然是只有核心逻辑的伪代码:

public T get() {        Thread t = Thread.currentThread(); //先获得当前线程        if (t.threadLocals != null) { //判断当前线程上的threadLocals成员是否为空            return (T)t.threadLocals.get(this); //不为空,则以ThreadLocal对象作为key值得到value,然后返回。        }        return setInitialValue(); //返回初始值    }

理清了get和set方法,相信整个ThreadLocal的实现方式,大家应该都比较清楚了。

 来自简书. 作者:我爱纽约先生的一段话(链接在文末)

作者之所以这样设计,我相信是经过了充分考虑的。我能想到的一点,就是考虑了对象的生命周期。

ThreadLocal要为每个线程维护value值,所以它的生命周期一般是长于线程对象生命周期的。一个长生命周期的对象维护一个短生命周期对象的引用,就有可能内存泄露,除非开发者要手动remove掉。

而把value存放在Thread上,一切就可以完美的解决。因为这个value对象是专门为Thread对象而存在的,所以value对象和Thread对象的生命周期应该完全一致。把value对象存放在Thread对象里,则不会有内存泄露的风险。虽然,Thread会维护一个ThreadLocal的引用(实际上是个弱引用),但是如前所说,一个短生命周期的对象维护长生命周期对象的引用,一般没什么问题。


📜 第三章 - 如何使用ThreadLocal

使用ThreadLocal非常简单。我们只需创建一个ThreadLocal对象,并重写initialValue()方法,定义每个线程初始的变量值。然后,通过调用get()方法可以获取当前线程的副本,而set()方法用于设置线程局部变量的值。

public class ThreadLocalExample {    private static ThreadLocal threadLocal = new ThreadLocal() {        @Override        protected Integer initialValue() {            // 设置每个线程的初始值为0            return 0;        }    };        public static void main(String[] args) {        // 创建3个线程执行任务        Thread t1 = new Thread(new MyRunnable());        Thread t2 = new Thread(new MyRunnable());        Thread t3 = new Thread(new MyRunnable());        t1.start();        t2.start();        t3.start();        try {            t1.join();            t2.join();            t3.join();        } catch (InterruptedException e) {            e.printStackTrace();        }    }    static class MyRunnable implements Runnable {        @Override        public void run() {            int value = threadLocal.get();            System.out.println("线程:" + Thread.currentThread().getName() + ",初始值:" + value);                        // 修改初始值            value += 5;            threadLocal.set(value);                        // 再次获取修改后的值            int updatedValue = threadLocal.get();            System.out.println("线程:" + Thread.currentThread().getName() + ",修改后的值:" + updatedValue);        }    }}

 在上述代码中,我们创建了一个名为threadLocal的ThreadLocal对象,并重写了它的initialValue()方法,用于定义每个线程初始的变量值(这里设置为0)。

然后,我们创建了3个线程,并在每个线程的run()方法中操作ThreadLocal对象。首先,通过get()方法获取当前线程的副本,并输出初始值。然后,我们使用set()方法修改初始值,并再次使用get()方法获取修改后的值。

运行这段代码,你会看到每个线程都有自己独立的初始值和修改后的值。这表明每个线程通过ThreadLocal对象进行了数据隔离,互不干扰。

你可以根据自己的需求来定义ThreadLocal对象的值和操作逻辑。


🌟 第四章 - ThreadLocal的应用场景

ThreadLocal的应用非常广泛,下面为大家介绍几个特别实用的场景:

1️⃣ 数据库连接管理:在多线程环境下,使用ThreadLocal可以方便地管理数据库连接,每个线程都能获取到自己独立的连接副本,避免了线程安全和资源竞争问题。

2️⃣ Web应用用户信息存储:对于一个WEB应用程序,可以使用ThreadLocal将当前用户的登录信息存储在线程局部变量中,这样在后续的请求处理过程中就无需传递这些信息了。

3️⃣ 日志跟踪:ThreadLocal还可以用于日志跟踪,每个线程都有自己的日志副本,方便调试和定位问题。


🔮总结

💡Thread里面存储着各自的ThreadLocalMap, 并且Thread的每一个ThreadLocal会根据Thread的生命周期进行销毁, 每个ThreadLocalMap都属于某一个Thread, 而ThreadLocal只是ThreadLocalMap里面的一个而已, ThreadLocal对象实例就是Map中的键, 根据它就可以得到value, 一个ThreadLocal只能为一个Thread服务一个数据, 但是同时可以为其他Thread服务.

💡为什么是一个ThreadLocal给Thread关联一个数据呢?

因为set()方法中, t.threadLocals.set(this, value); //如果threadLocals不等于空,则set value,ThreadLocal对象作为key值。

不管你怎么弄都是一个ThreadLocal对应着一个相应的Thread的

📷 图四:ThreadLocal原理图

🎉 精彩的ThreadLocal世界就在眼前!无论你是面对高并发的系统,还是只是想学习Java多线程编程,ThreadLocal都能帮助你轻松解决问题。希望这篇推荐能给你带来灵感与启发。如果你有其他关于ThreadLocal的经验和想法,也欢迎在评论区与我分享。下次再见!👋

🫰🫰🫰以下是对我帮助很多的文章:

ThreadLocal到底是个什么东西? - 简书 (jianshu.com)

来源地址:https://blog.csdn.net/dandelionl_/article/details/132252262

--结束END--

本文标题: 【Java】线程数据共享和安全 -ThreadLocal

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

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

猜你喜欢
  • 【Java】线程数据共享和安全 -ThreadLocal
     🎄欢迎来到@边境矢梦°的csdn博文🎄  🎄本文主要梳理线程数据共享和安全 -ThreadLocal🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做...
    99+
    2023-09-08
    java 开发语言 ThreadLocal servlet tomcat javascript
  • Java 多线程之间共享数据
    目录1、线程范围的共享变量2、使用Map实现线程范围内数据的共享3、ThreadLocal实现线程范围内数据的共享4、优化5、实例1、线程范围的共享变量 多个业务模块针对同一个sta...
    99+
    2024-04-02
  • Java多线程之间如何共享数据
    这篇文章主要介绍Java多线程之间如何共享数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、线程范围的共享变量多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象pu...
    99+
    2023-06-25
  • java中ThreadLocal避免线程不安全的方法
    这篇文章主要介绍java中ThreadLocal避免线程不安全的方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、说明ThreadLocal 翻译是线程本地变量的意思, ThreadLocal 就是用来创建线程的...
    99+
    2023-06-15
  • Python 多进程 多线程数据共享
    #!/usr/bin/env python # -*- coding:utf-8 -*- # author: Changhua Gong from multiprocessing import Process, Queue import o...
    99+
    2023-01-31
    多线程 进程 数据
  • Python 并发编程中的数据共享:探索安全的共享机制
    介绍 在多线程或多进程的并发 Python 程序中,多个线程或进程可以同时访问和修改共享数据。这可能会导致数据竞争和不一致,从而破坏程序的完整性和正确性。因此,在并发编程中管理数据共享至关重要。 锁:互斥访问 锁提供了一种用于确保同一时...
    99+
    2024-02-18
    Python 并发编程 数据共享 线程安全 事件 队列
  • Java如何实现多个线程之间共享数据
    目录实现多个线程之间共享数据一、 如果每个线程执行的代码相同二、 如果每个线程执行的代码不同多线程之间共享数据的方式探讨方式一:代码一致方式二:代码不一致实现多个线程之间共享数据 一...
    99+
    2024-04-02
  • java多线程共享全局变量怎么实现
    在Java中,多线程共享全局变量可以通过以下几种方式实现: 使用volatile关键字:将共享变量声明为volatile类型,确...
    99+
    2023-10-23
    java
  • python多线程数据共享怎么实现
    在Python中,可以使用`threading`模块来实现多线程数据共享。具体步骤如下: 导入`threading`模块:`im...
    99+
    2023-10-26
    python
  • Java多线程 - 线程安全和线程同步解决线程安全问题
    文章目录 线程安全问题线程同步方式一: 同步代码块方式二: 同步方法方式三: Lock锁 线程安全问题 线程安全问题指的是: 多个线程同时操作同一个共享资源的时候可能会出现业务安全问题,称为线程安全问题。 举例:...
    99+
    2023-08-20
    java 安全 jvm
  • 微信小程序--》小程序—全局数据共享和分包
    🏍️作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名在校大学生 🛵个人主页:亦世凡华、 🛺系列专栏:微信小程序 🚲座右铭:人生亦可燃烧,亦可腐败,我愿燃烧,耗尽...
    99+
    2023-09-13
    微信小程序 小程序 开发语言 前端
  • 浅谈Java安全编码之文件和共享目录的安全性
    目录一、linux下的文件基本权限二、linux文件的特殊权限2.1、Set UID 和 Set GID2.2、Sticky Bit2.3、SUID/SGID/SBIT权限设置三、文...
    99+
    2024-04-02
  • Java并发编程之线程之间的共享和协作
    目录一、线程间的共享1.1 ynchronized内置锁1.2 volatile关键字1.3 ThreadLocal1.4 Spring的事务借助ThreadLocal类1.4.1 ...
    99+
    2024-04-02
  • 如何在 Goroutine 中安全地获取共享数据?
    go 中可通过以下方法安全获取 goroutine 的共享数据:1. 互斥锁(mutex):允许一个 goroutine 独占访问共享数据;2. 通道(channel):协调对共享数据的...
    99+
    2024-05-15
    并发安全
  • Java中怎么利用多线程锁实现数据同步共享
    Java中怎么利用多线程锁实现数据同步共享,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。大多数应用程序要求线程互相通信来同步它们的动作。在Java程序中最简单实现同步的方法就是...
    99+
    2023-06-17
  • mysql各个内存参数的介绍,分线程独享和全局共享两大类
    mysql的内存参数分别有两大类,一类是线程独享的内存,一类是全局共享的内存 线程独享内存:join_buffer_size、sort_buffer_size、read_buffer_size顺序读取数...
    99+
    2024-04-02
  • python多线程数据共享的方法是什么
    Python中多线程数据共享的方法有以下几种:1. 全局变量:在多个线程中使用全局变量进行数据共享。但是需要注意的是,全局变量在多线...
    99+
    2023-08-12
    python
  • java中多线程和线程安全是什么
    这篇文章给大家分享的是有关java中多线程和线程安全是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是进程?电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中...
    99+
    2023-06-25
  • Java线程安全与非线程安全解析
    ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题。面对这样的问题,回答是:ArrayList是非线...
    99+
    2023-05-31
    java 线程安全 ava
  • Java多线程下解决数据安全问题
    目录同步代码块同步方法lock锁同步代码块 基本语句 synchronized (任意对象) { 操作共享代码 } 代码示例 public class SellTicket ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作