关于ThreadLocal的使用

本文通过一个具体的示例详细介绍了ThreadLocal的基本用法及其在多线程环境中的优势。通过mmain.java、SQLSearch.java和ThreadLocalUtils.java三个类的配合,演示了如何为每个线程分配独立的变量副本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

             ThreadLocal 是为了更好的写多线程,而使用的变量,个人理解不是通常利用ThreadLocal变量来处理线程同步关系的。而是为了方便书写代码。

参考了博文:原博文 ,我又将其冗余的部分修改了,为了更好理解,下面做一些必要的说明。

总共有三个类:mmain.java   SQLSearch.java ThreadLocalUtils.java

             mmain.java 就是java的运行主类(包含main的方法),SQLSearch.java 是为了获取到调用该方法所对应的线程变量,并显示信息。 ThreadLocalUtils.java 定义了用来保存各个线程所持有变量的集合。

              源码如下:

ThreadLocalUtils.java

public class ThreadLocalUtils{
    public static final ThreadLocal<String> DATA = new ThreadLocal<String>();
}

SQLSearch.java

public class SQLSearch{
    public String run(){
        return search(ThreadLocalUtils.DATA.get()); //将会获得对应的线程的String对象,也就是在ThreadLocal尖括号之间的类型  
    }

    private String search(String name){
        String result = null;
        if(name.equals("S")){
            result = (name+":165");
        }
        if(name.equals("M")){
            result = (name+":170");
        }
        if(name.equals("L")){
            result = (name+":175");
        }
        if(name.equals("XL")){
            result = (name+":180");
        }
        if(name.equals("XXL")){
            result = (name+":185+");
        }
        return result;
        }
}
mmain.java :

public class mmain{
    static String[] names = new String[]{"S","M","L","XL","XXL"};     //衣服的尺码
    static int index = 0;                                             //为了分别设置线程名称

    public static void main(String args[]){
        for(int i = 0; i < names.length; i++){
            Thread t = new Thread(){
                public void run(){
                    ThreadLocalUtils.DATA.set(this.getName());       //设置当前线程的名称
                    System.out.println(new SQLSearch().run());       //利用SQLSearch中run方法获取到当前线程的线程名
                }
            };
            t.setName(names[index++]);                               //将尺码的名称依次设置为线程名
            t.start();                                               //启动线程
        }
    }
}
执行的结果如下:

sely@com:~/sylinux/ThreadLocal$ java mmain
S:165
M:170
L:175
XL:180
XXL:185+
代码执行的流程:

         1.  执行main函数,进入for循环,生成了第一个thread()

         2.  设置第一个thread的线程名,index为0,所以设置的线程名为“S”

         3.  执行线程的start方法,就会调用run()方法,也就是重写的run方法体,方法体执行了ThreadLocalUtils.DATA.set(this.getName());

              DATA是static属性,属于ThreadLocalUtils这个类的,不属于任何它的实例化对象所有,可以用类名.属性名的方法直接调用。DATA这个变量是ThreadLocal对象,

              <T>之间就是这个变量所保存的数据类型。

         4.  ThreadLocal<T>类提供了一下的方法:

                     T  get()  :  Returns the value in the current thread's copy of this thread-local variable.

                     protected  T  initialValue() :   Returns the current thread's "initial value" for this thread-local variable.

                     void   remove()  :  Removes the current thread's value for this thread-local variable.

                     void   set(T value) : Sets the current thread's copy of this thread-local variable to the specified value.

         5.  代码利用DATA.set()方法,就会将当前线程的名称(String类型)设置到DATA中去,调用set的线程,此时就是第一个创建的线程,所以set进DATA就是“S”

         6.  第二次利用set()方法又会设置当前线程名,  这时同样调用的是第二个线程的getName(),设置到DATA中。

               .........

         7.  设置过程中,又利用new SQLSearch()对象的run方法,来取出它保存在DATA中的String,调用 ThreadLocalUtils.DATA.get()方法,就会获得调用这个方法所属于线程开始设置的变量。跟set差不多,所以每次get都能够区分开线程所拥有的值了。



ThreadLocal是一个Java类,用于在多线程环境下保存线程本地变量的副本。通过创建ThreadLocal对象,每个线程都可以拥有自己独立的变量副本,互不干扰。 使用ThreadLocal的过程如下: 1. 创建一个ThreadLocal对象,可以指定泛型类型。 2. 在每个线程中,通过ThreadLocal对象的`get()`方法获取当前线程的变量副本。如果当前线程没有设置过变量值,则会使用默认值进行初始化。 3. 在每个线程中,通过ThreadLocal对象的`set(value)`方法设置当前线程的变量值。 4. 在每个线程中,通过ThreadLocal对象的`remove()`方法移除当前线程的变量副本。 需要注意的是,ThreadLocal对象的生命周期与Thread对象的生命周期一样长。当ThreadLocal对象被垃圾回收时,关联的变量副本也会被回收。 在ThreadLocal内部,使用ThreadLocalMap来存储每个线程的变量副本。ThreadLocal的实例作为key,变量值作为value。ThreadLocalMap可以使用强引用或弱引用来引用ThreadLocal对象。如果使用强引用,当ThreadLocal对象被回收时,如果没有手动删除对应的变量副本,会导致内存泄漏。如果使用弱引用,当ThreadLocal对象被回收时,对应的变量副本也会被回收。 总结来说,ThreadLocal是一种线程本地变量,通过保存每个线程的变量副本,实现了多线程环境下的线程隔离。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ThreadLocal使用与原理](https://blog.youkuaiyun.com/qq_35190492/article/details/116431270)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ThreadLocal使用详解](https://blog.youkuaiyun.com/LJJZJ/article/details/88763666)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值