Java线程上下文-ThreadLocal的那些事

一、概述

ThreadLocal: 通常被称作线程本地变量或者线程本地存储。其含义是ThreadLocal为变量在每个线程中都创建一个副本,则每个线程可以访问自身内部的副本变量。
概念总是抽象而且晦涩的,我们从两个例子说起。

1、对象间/方法间跨层传递

如下图,有个多层调用的情况,如果我们需要传递某个中间结果在这几层调用关系之间,应该怎么处理呢?
多层调用

  • 一种简单的思路是,把每个函数新增一个参数,然后依次传递下去。但是,如果参数过多,或者某一个函数为公共函数,不允许我们随意添加参数的话,那该怎么处理呢?
  • 另一种思路,设置一个单例类,实时保存该数据。实存实取。也能保证其在各个函数之间的传递。但是,如果是多线程操作怎么保证单例数据不被污染?
    假设,我们在A.fun1()之中将数据保存在单例类中,然后在之后的其他函数中操作该数据。如果是多线程的环境,如果同时有多个线程同时操作入口函数A.fun1(),则单例保存的数据则会被污染。
  • 还有一种思路,就是使用ThreadLocal为该数据在每个线程中都创建一个副本,则线程之间则不会互相影响。如下代码,通过ThreadLocal,我们可以使数据在对象间/方法间进行传递。
public class ThreadLocalDemo {
    private ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    private void fun1() {
        threadLocal.set(System.nanoTime());
        System.out.println("fun1:" + threadLocal.get());
        fun2();
    }

    private void fun2() {
        System.out.println("fun2:" + threadLocal.get());
        fun3();
    }

    private void fun3() {
        System.out.println("fun3:" + threadLocal.get());
        threadLocal.remove();
    }

    public static void main(String[] args) {
        ThreadLocalDemo demo = new ThreadLocalDemo();
        demo.fun1();
    }
}

2、线程间的数据隔离

如果需要将一个单线程的应用移植到到多线程的环境下,就需要将共享的一些全局变量转换为ThreadLocal对象;这相当于ThreadLocal为每个线程都创建了一个该全局变量的副本。保证了其线程安全性。

但是,TheadLocal并不是解决高并发下共享资源的方式。大多数情况下,ThreadLocal存储的是一个new的新对象。但是如果其存储一个对象的引用,也会面临资源竞争的情况。

  • 例子1:ThreadLocal与Synchronized区别
    好多人都说ThreadLocal和Synchroized一样,实现了线程同步。那我们看个例子。
    假设有一个static int a = 0;,共有5个线程对其进行++操作,保险起见,我们对++进行加锁(Sync)。这样在执行完之后,a == 5,毫无疑问。
    同样的,我们起初使用ThreadLocal保存a =
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocal类是Java线程编程中非常有用的一个类,它提供了一种线程本地变量的机制。线程本地变量是指每个线程都有自己独立的变量副本,互不干扰,可以避免线程间的数据共享问题。下面是ThreadLocal类的用法及一些深入的解释。 1. 基本用法: ThreadLocal类的使用非常简单,可以通过以下几个步骤实现: - 创建ThreadLocal对象:`ThreadLocal<T> threadLocal = new ThreadLocal<>()` - 设置线程本地变量:`threadLocal.set(value)` - 获取线程本地变量:`T value = threadLocal.get()` - 清除线程本地变量:`threadLocal.remove()` 2. 实际应用: ThreadLocal类在多线程编程中有广泛的应用,特别是在以下场景中: - 数据库连接管理:每个线程都可以拥有自己的数据库连接,避免了线程间共享连接的问题。 - 务管理:每个线程可以独立管理自己的务,避免了务数据的混乱。 - 用户身份信息传递:在Web应用中,可以将用户身份信息存储到ThreadLocal中,方便不同组件访问。 - 线上下文信息传递:可以将一些线上下文信息存储到ThreadLocal中,方便不同线程间的信息传递。 3. 实现原理: ThreadLocal类的实现原理比较复杂,它通过一个ThreadLocalMap来维护每个线程的变量副本。在每个ThreadLocal对象中都有一个ThreadLocalMap实例,用于存储线程本地变量的值。当调用ThreadLocal的set方法时,实际上是将值存储到当前线程的ThreadLocalMap中;当调用get方法时,实际上是从当前线程的ThreadLocalMap中获取值。 4. 注意项: - 内存泄漏:由于ThreadLocalMap中的Entry对象使用ThreadLocal的弱引用作为键,如果ThreadLocal没有被及时清理,可能会导致内存泄漏问题。因此,在使用完ThreadLocal后,应该调用remove方法进行清理。 - 初始化值:通过重写ThreadLocal的initialValue方法,可以为每个线程的变量副本提供一个初始值。 总结: ThreadLocal类提供了一种简单而有效的方式来实现线程本地变量。它在多线程编程中有广泛的应用,可以避免线程间数据共享的问题。但需要注意内存泄漏和初始值的问题。希望以上解释对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值