线程安全—ThreadLocal

这篇具有很好参考价值的文章主要介绍了线程安全—ThreadLocal。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

定义:

ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为每个线程都创建了一个副本,存的是自己,那么每个线程可以访问自己内部的副本变量。

ThreadLocal是用空间换取时间,synchronized关键字是用时间换空间。

ThreadLocal操作值的时候是取得当前线程的ThreadLocalMap对象,然后把值设置到了这个对象中,这样对于不同的线程得到的就是不同的ThreadLocalMap,那么向其中保存值或者修改值都只是会影响到当前线程,这样就保证了线程安全。

使用:

由于Thread中包含变量ThreadLocalMap,因此ThreadLocalMap与Thread的生命周期是一样长,如果都没有手动删除对应key,都会导致内存泄漏。

但是使用弱引用可以多一层保障:弱引用ThreadLocal不会内存泄漏,对应的value在下一次ThreadLocalMap调用set(),get(),remove()的时候会被清除。

因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

ThreadLocal正确的使用方法:
每次使用完ThreadLocal都调用它的remove()方法清除数据
将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。

使用场景:

1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。

2、线程间数据隔离,【你访问你的,我访问我的,不会相互干扰】

3、进行事务操作,用于存储线程事务信息。

4、数据库连接,Session会话管理。

5、MDC链路追踪。

如何解决线程池中的值传递功能?(ThreadLocal,InheritableThreadLocal ,TransmittableThreadLocal区别)
InheritableThreadLocal 继承 ThreadLocal,主要用于子线程创建时,需要自动继承父线程的ThreadLocal变量,方便必要信息的进一步传递。

由于InheritableThreadLocal是在异步子线程初始化时进行的设置,而线程只会初始化一次,就会导致子线程中的ThreadLocal一直是同一个。

开发中,一般会用池化的技术来管理多个线程,即会用到线程池。在线程池中,核心线程一般来说是不会死的,他们会被反反复复使用。用InheritableThreadLocal的问题在于,threadLocal只在子线程初始化的时候进行了传递,当这个子线程完成了第一个任务,随后处理其他请求时,这个子线程中的threadLocal却还一直是第一个请求时设置的那个threadLocal,就会导致出错。

在遇到线程池等会池化复用线程的执行组件情况下,就需要通过TransmittableThreadLocal类来实现线程值传递。

MDC链路追踪如何使用ThreadLocal?

异步服务的统一API,例如:

    @Override
    @Async
    public <T> void execute(Map<String, String> logContext, Consumer<T> consumer, T t) {
        this.dealLogContext(logContext);
        LOGGER.debug("发起异步调用,设置线程日志上下文");
        try {
            LOGGER.debug("调用函数");
            consumer.accept(t);
            LOGGER.debug("发起异步调用完成");
        } catch (Exception e) {
            LOGGER.warn(e, "发起异步调用异常");
        } finally {
            MDC.clear();
        }
    }
    private void dealLogContext(Map<String, String> logContext) {
        MDC.clear();
        if (logContext == null) {
            logContext = new HashMap<>();
            logContext.put("traceId", Logger.genTraceId());
        }
        MDC.setContextMap(logContext);
    }

对于消息队列MQ,则需要通过传参的方式,在消费者端,手动给当前线程ThreadLocal赋值。文章来源地址https://www.toymoban.com/news/detail-669435.html

到了这里,关于线程安全—ThreadLocal的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Swift如何保证线程安全

    Swift可以通过以下几种方式来保证线程安全 使用互斥锁(Mutex):使用互斥锁可以防止多个线程同时访问共享数据,保证线程安全。 使用OSAtomic操作:OSAtomic操作可以在多线程环境中安全地执行原子操作。 使用DispatchQueue:DispatchQueue可以使用GCD技术实现线程安全。您可以使用

    2024年02月13日
    浏览(39)
  • ConcurrentHashMap 是如何保证线程安全的,你知道么?

    阅读此篇文章,你需要有以下知识基础 Java内存模型,可见性问题 CAS HashMap底层原理 我们知道,在日常开发中使用的HashMap是线程不安全的,而线程安全类HashTable只是简单的在方法上加锁实现线程安全,效率低下,所以在线程安全的环境下我们通常会使用ConcurrentHashMap,但是又

    2024年01月22日
    浏览(82)
  • 【昕宝爸爸小模块】ConcurrentHashMap是如何保证线程安全的

    在JDK 1.7中,ConcurrentHashMap使用了分段锁技术 ,即将哈希表分成多个段,每个段拥有一个独立的锁。这样可以在多个线程同时访问哈希表时,只需要锁住需要操作的那个段,而不是整个哈希表,从而提高了并发性能。 虽然JDK 1.7的这种方式可以减少锁竞争,但是在高并发场景下

    2024年02月01日
    浏览(35)
  • 码出高效:Java开发手册笔记(线程安全)

        并发与并行的目标都是尽可能快地执行完所有任务。以医生坐诊为例,某个科室有两个专家同时出诊,这就是两个并行任务,其中一个医生,时而问诊,时而查看化验单,然后继续问诊,突然又中断去处理病人的咨询,这就是并发。在并发环境下,由于程序的封闭性全

    2024年02月08日
    浏览(38)
  • 结合底层源码介绍ConcurrentHashMap如何保证线程安全,佬会爱上这篇文章嘛

    前言: 本篇文章主要讲解 结合底层源码介绍ConcurrentHashMap如何保证线程安全 的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了😁 以下正文开

    2024年02月11日
    浏览(40)
  • Mybatis-plus更新多张表,保证事务安全的情况下使用异步多线程实现(待验证)

    要使用异步多线程更新多张表并保证事务安全,可以使用Spring框架的异步处理和事务管理功能。下面是一个简单的示例: 首先,需要在Spring配置文件中启用异步处理和事务管理。可以使用以下配置: 在Java代码中,可以使用 @Async 注解将方法标记为异步方法。在异步方法中,

    2024年04月11日
    浏览(37)
  • 无线路由器怎么设置或更改wifi密码防蹭网保证网络安全

    无线路由器的WiFi密码设置合理,有助于我们防蹭网,保证网络安全。怎样设置无线网络的密码呢,或者更改wifi密码呢?下面我以D-Link DI524M无线路由器为例来给大家演示一下。 步骤 1、在浏览器地址栏中输入路由器的管理网址http://192.168.0.1按回车。不同品牌的路由器管理信息

    2024年02月07日
    浏览(57)
  • HTTPS是如何保证安全的,web前端开发工程师,前端开发自学技巧

    非对称加密 浏览器发送给服务端 一系列加密方法 服务端发送给浏览器 加密方法以及公钥 之后浏览器通过公钥将数据加密传输给服务端,服务端收到数据使用私钥进行解密。服务端给浏览器发送数据,则使用私钥进行加密,浏览器收到服务端发送过来的数据,使用公钥进行

    2024年04月13日
    浏览(45)
  • java面试题(23):Spring Bean如何保证并发安全

    1 问题分析 我们知道默认情况下,Spring中的Bean是单例的,所以在多线程并发访问的时候,有可能会出现线程安全问题。 2 解决方案 有几个方面的解决思路: 我们可以设置Bean的作用域设置为原型(prototype),这样每次从容器中获取该 Bean 的时候,都会创建一个新的实例,避免

    2024年01月18日
    浏览(41)
  • 企业级项目开发中保证接口安全的11个小技巧,详细案例指导

    企业级项目开发中保证接口安全的11个小技巧,详细案例指导。 如何保证接口的安全性? 1 参数校验 保证接口安全的第一步,也是最重要的一步,需要对接口的请求参数做校验。 如果我们把接口请求参数的校验做好了,真的可以拦截大部分的无效请求。 我们可以按如下步骤

    2024年01月23日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包