文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java中ThreadLocal线程变量的实现原理是什么

2023-07-02 13:17

关注

这篇文章主要介绍了Java中ThreadLocal线程变量的实现原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中ThreadLocal线程变量的实现原理是什么文章都会有所收获,下面我们一起来看看吧。

ThreadLocal是什么?

ThreadLocal 使得我们可以创建线程私有的变量, 这个变量相对于其他线程来说是不可见的,ThreadLocal为变量在每个线程中都创建了一个副本 , 每个线程可以访问自己私有的线程变量,代码示例如下 : 

public class ThreadLocalDemo {     //创建一个ThreadLocal对象,用来为每个线程会复制保存一份变量,实现线程封闭    private  static ThreadLocal<Integer> localNum = new ThreadLocal<Integer>(){        @Override        protected Integer initialValue() {            return 1;        }    };     public static void main(String[] args) {          //线程0          new Thread(){              @Override              public void run() {                   localNum.set(1);                  try {                      Thread.sleep(2000);                  } catch (InterruptedException e) {                      e.printStackTrace();                  }                  localNum.set(localNum.get()+10);                  System.out.println(Thread.currentThread().getName()+":"+localNum.get());//11              }          }.start();        //线程1        new Thread(){            @Override            public void run() {                localNum.set(3);                try {                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                localNum.set(localNum.get()+20);                System.out.println(Thread.currentThread().getName()+":"+localNum.get());//23            }        }.start();                System.out.println(Thread.currentThread().getName()+":"+localNum.get());//0    }}

如上所述, 算上main线程与新建的两个线程 ,总共三个线程 , 每个线程都包含自己的私有变量,此处我们设置值1 , set() 和 get() 方法用来设置值和获得值, 执行结果如下 : 

Java中ThreadLocal线程变量的实现原理是什么

ThreadLocal实现原理分析

ThreadLocal是一个泛型类 , 可以接受任何类型的对象 , 其内部维护了一个ThreadLocalMap 的静态内部类,  我们使用的 get(), set()等其实都来自这个类, 每次都会为当前线程创建一个ThreadLocalMap对象, 用来记录私有的值

Java中ThreadLocal线程变量的实现原理是什么

先看 set() 方法

public void set(T value) {    //拿到当前线程    Thread t = Thread.currentThread();    //拿到当前线程map    ThreadLocalMap map = getMap(t);    if (map != null)        //存在设置值        map.set(this, value);    else        //不存在则创建        createMap(t, value); }
void createMap(Thread t, T firstValue) {    //threadLocals属性即为此map    t.threadLocals = new ThreadLocalMap(this, firstValue);}

接着是get() 方法

public T get() {    //拿到当前线程    Thread t = Thread.currentThread();    //拿到当前线程对应的map    ThreadLocalMap map = getMap(t);    //如果已有map    if (map != null) {        //取值操作, 拿到对应的Entry        ThreadLocalMap.Entry e = map.getEntry(this);        if (e != null) {           @SuppressWarnings("unchecked")           T result = (T)e.value;           return result;        }    }    //没有map, 则去创建初始化一个map    return setInitialValue();}
private T setInitialValue() {    //initialValue()方法返回的value为null    T value = initialValue();    //拿到当前线程去创建对应的map    Thread t = Thread.currentThread();    ThreadLocalMap map = getMap(t);    if (map != null)        map.set(this, value);    else        createMap(t, value);    return value;}

ThreadLocal可以理解为对ThreadLocalMap的封装

ThreadLocal内存泄漏问题

在ThreadLocalMap中 , 使用 ThreadLocal 的弱引用作为 key 

Java中ThreadLocal线程变量的实现原理是什么

这样的话, 如果一个ThreadLocal不存在外部强引用时, 那么key注定要被GC回收 , 这样导致ThreadLocalMap 中key为null , 而value还存在着强引用链

一个线程可以同时拥有多个ThreadLocal, 如果作为弱引用的key被回收后, value还不能被回收,那么这就导致此ThreadLocal的生命周期和此线程是一样长的(因为线程执行完毕后此value的强引用链才会断), 如果线程一直不结束, 堆积的value也一直无法被回收, 那么就会产生内存泄漏问题

这里解决问题的方式是 : 每次使用完ThreadLocal后都调用它的remove()方法清除数据

public void remove() {    ThreadLocalMap m = getMap(Thread.currentThread());    if (m != null)       m.remove(this);}

这里我们再来看一下key作为强弱引用的区别

如果key作为强引用, 那么它的生命周期和线程一样长,存在稳定的强引用链,无法被回收,产生内存泄漏问题, 而如果作为弱引用, GC则会自动的去回收它们, 在后续的remove()方法中也可以更好的去回收value , 所以我们一般将ThreadLocal设计成 private static 的, 在使用完后用remove()方法去手动删除它们

关于“Java中ThreadLocal线程变量的实现原理是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java中ThreadLocal线程变量的实现原理是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯