从代码案例了解ThreadLocal的作用以及原理

本文主要是对上篇中ThreadLocal进行一个小讲解https://blog.csdn.net/qq_38340127/article/details/109866392,若有错误希望观众老爷们帮忙指出下,我好改进谢谢。

目录

 

一、ThreadLocal的作用

1.1  为啥要将key设置为弱引用

1.2 为啥不将value也设置为弱引用

二、用static修饰ThreadLocal

三、用final修饰ThreadLocal

四、 SimpleDateFormat线程不安全如果使用不当会怎么样


一、ThreadLocal的作用

在源码中有一段这样的注释:

 * This class provides thread-local variables.  These variables differ from
 * their normal counterparts in that each thread that accesses one (via its
 * {@code get} or {@code set} method) has its own, independently initialized
 * copy of the variable.  {@code ThreadLocal} instances are typically private
 * static fields in classes that wish to associate state with a thread (e.g.,
 * a user ID or Transaction ID).

翻译一下就是

*此类提供线程局部变量。这些变量不同于

*它们的正常对应关系是每个线程访问一个线程(通过

*{@code get}或{@code set}方法)有自己的独立初始化

*变量的副本。{@code ThreadLocal}实例通常是私有的

*类中希望将状态与线程关联的静态字段(例如。,

*用户ID或事务ID)。


 * <p>Each thread holds an implicit reference to its copy of a thread-local
 * variable as long as the thread is alive and the {@code ThreadLocal}
 * instance is accessible; after a thread goes away, all of its copies of
 * thread-local instances are subject to garbage collection (unless other
 * references to these copies exist).

*<p>每个线程都有一个对其本地线程副本的隐式引用

*变量,只要线程是活动的并且{@code ThreadLocal}

*实例是可访问的;在线程离开后,它的所有副本

*线程本地实例要进行垃圾回收(除非

*存在对这些副本的引用)。

具体的总结下就算是,提供线程局部变量,具体就是首先通过set,然后再通过get,这样就可以获取到之前设置到线程中的值了。那么我们就用代码来测试下:

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test {

    public static void main(String[] args) {
        final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
        threadLocal.set(new SimpleDateFormat("HH:mm"));
        SimpleDateFormat tmp = threadLocal.get();
        Date now = new Date();
        String value = tmp.format(now);
        System.out.println(value);
        // 新线程中获取对应的SimpleDateFormat
        new Thread(new Runnable(){
            public void run() {
                SimpleDateFormat tmp = threadLocal.get();
                System.out.println(tmp);
            }
        }).start();
    }

}

上面的结果如果根据注释来的话,新线程里面的SimpleDateFormat获取到的应该是null,那么具体是这样么?

最终输出结果
22:18
null

结果和注释一毛一样,那么他是how to do it?????

具体查看下set方法:

// 这块就是ThreadLocal所调用的set方法
    public void set(T value) {
        // 获取当前线程
        Thread t = Thread.currentThread();
        // 根据当前线程获取对应的ThreadLocalMap 
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
// 看完代码应该就是对应的ThreadLocalMap  其作用咯?具体查看下getMap方法
    ThreadLocalMap getMap(Thread t) {
        // 意思就是说ThreadLocalMap其实就是线程的一个变量0 0原来如此
        return t.threadLocals;
    }
// 通过Thread中的源码我们就能看到原来是有这么一个值,放在那里
 ThreadLocal.ThreadLocalMap threadLocals = null;

//可是Thred代码下一行还有一个,这个又是干啥的?具体可以后续在讨论
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

那么根据这个意思就是获取当前线程,然后往这个线程里塞个变量,这个变量是通过Map形式进行key(而这个key就是对应的ThreadLocal),value存储的,下次获取的时候根据这个ThreadLocal就能拿到value了。

//如果map存在直接放进去
        private void set(ThreadLocal<?> key, Object value) {

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值