Java中 ThreadLocal 简介

1、ThreadLocal 作用

线程隔离:因为他的 key 是当前线程,所以不同线程 key 不同
线程安全:因为线程隔离,所以线程安全

2、使用介绍

就三个方法:set、get、remove

public class Test {

    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public static void main(String[] args) {
                threadLocal.set("hello world");
                threadLocal.get();
                threadLocal.remove();
            }
        });
    }
}

3、remove 方法

3.1 不使用 remove 方法

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public static void main(String[] args) {
        ExecutorService a = Executors.newFixedThreadPool(2);
        a.submit(() -> {
            for (int b=1;b<3;b++){
                System.out.println("线程名:"+Thread.currentThread().getName());
                System.out.println("初始值:"+threadLocal.get());

                threadLocal.set("hello world");

                System.out.println("修改后的值:"+threadLocal.get());
                System.out.println("-----------------------------------------");

//                threadLocal.remove();
            }
        });
    }
}

打印如下:

线程名:pool-1-thread-1
初始值:null
修改后的值:hello world
-----------------------------------------
线程名:pool-1-thread-1
初始值:hello world
修改后的值:hello world
-----------------------------------------

3.2 使用 remove 方法

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public static void main(String[] args) {
        ExecutorService a = Executors.newFixedThreadPool(2);
        a.submit(() -> {
            for (int b=1;b<3;b++){
                System.out.println("线程名:"+Thread.currentThread().getName());
                System.out.println("初始值:"+threadLocal.get());

                threadLocal.set("hello world");

                System.out.println("修改后的值:"+threadLocal.get());
                System.out.println("-----------------------------------------");

//                threadLocal.remove();
            }
        });
    }
}

打印如下:

线程名:pool-1-thread-1
初始值:null
修改后的值:hello world
-----------------------------------------
线程名:pool-1-thread-1
初始值:null
修改后的值:hello world
-----------------------------------------

3.3 总结

不使用remove方法后续相同线程依然能获取之前set的值,因此方法介绍后一定要调用 remove 方法

4、底层原理

ThreadLocal 底层是通过 ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal对象) 中都存在一个ThreadLocalMap, Map的key为ThreadLocal对象, Map的value为需要缓存的值
在这里插入图片描述
如上所示,ThreadLocal 里面其实就是一个 ThreadLocalMap,然后这个ThreadLocalMap里面是一个个entry对象,每个entry对象可以理解成存储的不同线程信息,entry里面的key存的就是一个ThreadLocal 对象,value就是你set进去的值。

5、使用注意事项

  • 内存泄漏:由于ThreadLocal的生命周期和线程的生命周期不同,如果不注意及时清理ThreadLocal变量,可能会导致内存泄漏。因此,在不再需要使用ThreadLocal时,应调用remove()方法将其从当前线程中清除,避免线程结束后仍然持有对该变量的引用。
  • 共享变量问题:尽管ThreadLocal为每个线程提供了独立的变量副本,但它并不能解决线程间共享变量的同步问题。如果多个线程共享同一个ThreadLocal变量,需要自行处理线程间的同步操作,确保线程安全。
  • 内部使用慎重:在一些特定的情况下,如使用线程池或者异步任务执行框架,使用ThreadLocal需要格外小心。因为线程池中的线程可能会被复用,如果不正确地处理ThreadLocal变量,可能会导致数据混乱。

6、使用场景介绍

1、线程上下文传递:可以用于同一个线程参数传递,当镶嵌很多方法的时候不需要每一层都传递。
2、线程隔离安全:可以用于多线程并发但是每个线程独有的数据存储。

适合使用ThreadLocal的场景包括但不限于:Web应用中的用户身份验证、数据库连接管理、线程上下文传递等。在这些场景下,可以使用ThreadLocal轻松地在多线程环境下共享数据,提高并发性能和代码可维护性。

ThreadLocalJava的一个类,用于在多线程环境下实现线程本地变量。它提供了一种线程级别的数据隔离机制,使得每个线程都可以拥有自己独立的变量副本,互不干扰。每个线程都可以通过ThreadLocal对象来访问自己的变量副本,而不会影响其他线程的副本。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaThreadLocal详解](https://blog.csdn.net/licux/article/details/117292777)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [JavaThreadLocal详解(一篇就够了)](https://blog.csdn.net/qq_38721537/article/details/124565091)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [JavaThreadLocal详解](https://blog.csdn.net/qq_53729147/article/details/127967751)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值