线程数据共享和安全 -ThreadLocal

线程数据共享和安全 -ThreadLocal

1.什么是 ThreadLocal

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

ThreadLocal时序图

image-20220403160618777

2.快速入门ThreadLocal

T类

public class T {
    public static ThreadLocal threadLocal1 = new ThreadLocal();

    public static class MyThread implements Runnable{

        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            System.out.println("当前线程,"+name);
            /**
             *     public void set(T value) {
             *          //1.获取到当前线程
             *         Thread t = Thread.currentThread();
             *
             *         //2.将线程和ThradLocal进行关联
             *         //ThreadLocalMap是ThradLocal的静态内部类,Thread类中定义了 ThreadLocal.ThreadLocalMap threadLocals字段
             *         //getMap(t);===>  return t.threadLocals;对Thread的threadLocals进行了赋值
             *         ThreadLocalMap map = getMap(t);
             *
             *         //3.如果map不为空将threadloal最为key,传入的对象作为value存入到map中
             *         if (map != null)
             *             map.set(this, value);
             *         else
             *         //4.如果map为空则创建map并赋值
             *             createMap(t, value);
             *     }
             */
            threadLocal1.set(new Dog("一口", 2));
            new TService().update();
        }
    }

    public static void main(String[] args) {
        new Thread(new MyThread()).start();
    }
}

Dog

public class Dog {
    private String name;
    private Integer age;

    public Dog(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

TService

public class TService {

    public void update(){
        Thread thread = Thread.currentThread();
        System.out.println("当前线程,"+thread.getName());
        Object o = T.threadLocal1.get();
        System.out.println("TService 获取到对象="+o);
        new TDao().update();
    }
}

TDao

public class TDao {

    public void update() {
        Thread thread = Thread.currentThread();
        System.out.println("当前线程,"+thread.getName());
        Object o = T.threadLocal1.get();
        System.out.println("TDao 获取到对象="+o);

    }
}

测试结果

image-20220403161705040

Debug

image-20220403162134247

3.ThreadLocal 原理图

image-20220403164420460

你好!对于多线程编程,ThreadLocal类是一个非常有用的工具。它提供了线程本地变量的机制,使得每个线程都可以独立地存储和获取自己的变量副本。这在一些场景下非常有用,下面是一些ThreadLocal类的应用技巧: 1. 线程上下文信息传递:在多线程环境中,有时需要在线程之间传递一些上下文信息,例如用户身份认证信息、语言环境等。使用ThreadLocal类可以很方便地实现这一目的,每个线程都有自己独立的上下文信息副本,互不干扰。 2. 线程安全的数据存储:在多线程环境中,如果多个线程需要共享一份数据,可以使用ThreadLocal类来维护每个线程的局部副本。这样每个线程都可以独立地修改自己的副本,而不会影响其他线程的数据。 3. 避免传参:有些情况下,我们需要在多个方法之间传递某些参数,但是参数传递会增加代码复杂性。使用ThreadLocal类可以避免传参,每个方法可以直接从ThreadLocal中获取需要的参数值。 4. 事务管理:在一些事务场景中,我们可能需要在同一个线程中执行多个数据库操作,并保证这些操作在同一个数据库事务中。使用ThreadLocal类可以在线程中维护一个数据库连接对象,确保多个操作都使用同一个连接,实现事务的一致性。 需要注意的是,ThreadLocal类虽然提供了线程本地变量的机制,但并不是万能的解决方案。在使用ThreadLocal时,需要注意内存泄漏的问题,及时清理不再使用的资源。 希望以上内容对您有帮助!如需了解更多多线程编程相关内容,可以参考CSDN中张孝祥的相关文章。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值