线程内部存储---TheadLocal从使用到源码分析

ThreadLocal是什么?

ThreadLocalThreadLocal是一个线程内部用于存储数据的类,通过它可以在指定的线程中存储数据,数据存储以后,只有在该线程中可以获取到存储的数据,对于其它线程来说无法获取到数据。个人认为是一个线程内部的存储机制。

如何使用?


ThreadLocal<Boolean> threadLocal = new ThreadLocal<>();

这样就在一个线程创建了ThreadLocal这个对象,这个对象支持范性的,也就是说我们可以存储的自己想存的任意类型。


threadLocal.set(true);

这样我们就在当前所在线程,存储了true。


new Thread("Thread#1") {
@Override
public void run() {
System.out.println(threadLocal.get());
};
}.start();

我们在一个分线程去打印这个刚才存储的值会发现是null,因为这是在两个线程操作的。如果在当前线程获取则为正确刚才存的值。
如果想移除这个数据也很简单:

threadLocal.remove();

这就是threadLocal的使用,其实很简单。 主要记得是区分线程的就ok。

内部源码是如何实现的呢?

image.png
这就是treadLocal中的所有方法了,其实我们最关心的就是set和get方法。

我们先看set:


public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

这就是set方法,对就这么几行。
首先会通过Thread.currentThread();这个方法获取当前线程的Thread。然后通过getMap()获取 ThreadLocalMap对象。

ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

getMap中也很简单,就是返回这个线程的threadLocals, 这个ThreadLocal就是 Thread中的一个变量ThreadLocal.ThreadLocalMap threadLocals = null;
其实还是ThreadLocal中的内部类ThreadLocalMap;这里一会在分析,先顺着思路往下走。
获取map之后会根据判断如果不是null就进行set,也就是存储,如果是null就会调用createMap()方法进行创建这个ThreadMap。接下来在看是如何set和createMap的。

创建其实很简单,直接就是new一个。

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

set方法就稍微复杂了些,因为这也是核心内容。set方法在内部类ThreadLocalMap中,所以接下来分析下这个ThreadLocalMap类。

ThreadLocalMap

这个类在构造中创建了一个数组, new Entry[INITIAL_CAPACITY]; ,Entry里面就是一个object的对象,然后里面主要getEntry和set方法进行存取和读取。

““
private void set(ThreadLocal key, Object value) {

        Entry[] tab = table;
        int len = tab.length;
        int i = key.threadLocalHashCode & (len-1);

        for (Entry e = tab[i];
             e != null;
             e = tab[i = nextIndex(i, len)]) {
            ThreadLocal k = e.get();

            if (k == key) {//这里判断这个k和传进来的key是否相等
                e.value = value;//进行存储后return
                return;
            }

            if (k == null) {
                replaceStaleEntry(key, value, i);
                return;
            }
        }

        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
    }

““
看主要代码 判断k和传进来的key相等话就存储这个value
get方法:

“`
private Entry getEntry(ThreadLocal

我们再看get:


public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}

get里面也是要先获取当前的Thread这也就是为什么ThreadLocal获取和存储的都是只在当前线程的。

然后也是getMap方法获取这个ThreadLocalMap,这也就是为什么里面就一行代码,也要写成一个方来,因为这是中思路,其他地方获取直接调用就行,日后扩展的话一样方便。

再然后就是通过这个map去调用上面说的getEntry方法。

至此,我们就知道ThreadLocal的总体工作流程和思路了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值