threadlocal为什么是弱引用,threadlocal为什么是安全的

首页 > 技术 > 作者:YD1662023-04-15 23:32:30

我们先来回忆一下四种引用:

我们先来看看官方文档,为什么要设计为弱引用:

To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys. 为了应对非常大和长时间的用途,哈希表使用弱引用的 key。 复制代码

我再把ThreadLocal的引用示意图搬过来:

threadlocal为什么是弱引用,threadlocal为什么是安全的(9)

下面我们分情况讨论:

因此可以发现,使用弱引用作为Entry的Key,可以多一层保障:弱引用ThreadLocal不会轻易内存泄漏,对应的value在下一次ThreadLocalMap调用set,get,remove的时候会被清除。

实际上,我们的内存泄漏的根本原因是,不再被使用的Entry,没有从线程的ThreadLocalMap中删除。一般删除不再使用的Entry有这两种方式:

7. InheritableThreadLocal保证父子线程间的共享数据

我们知道ThreadLocal是线程隔离的,如果我们希望父子线程共享数据,如何做到呢?可以使用InheritableThreadLocal。先来看看demo:

public class InheritableThreadLocalTest { public static void main(String[] args) { ThreadLocal<String> threadLocal = new ThreadLocal<>(); InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>(); threadLocal.set("关注公众号:捡田螺的小男孩"); inheritableThreadLocal.set("关注公众号:程序员田螺"); Thread thread = new Thread(()->{ System.out.println("ThreadLocal value " threadLocal.get()); System.out.println("InheritableThreadLocal value " inheritableThreadLocal.get()); }); thread.start(); } } //运行结果 ThreadLocal value null InheritableThreadLocal value 关注公众号:程序员田螺 复制代码

可以发现,在子线程中,是可以获取到父线程的 InheritableThreadLocal 类型变量的值,但是不能获取到 ThreadLocal 类型变量的值。

获取不到ThreadLocal 类型的值,我们可以好理解,因为它是线程隔离的嘛。InheritableThreadLocal 是如何做到的呢?原理是什么呢?

在Thread类中,除了成员变量threadLocals之外,还有另一个成员变量:inheritableThreadLocals。它们两类型是一样的:

public class Thread implements Runnable { ThreadLocalMap threadLocals = null; ThreadLocalMap inheritableThreadLocals = null; } 复制代码

Thread类的init方法中,有一段初始化设置:

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { ...... if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); } static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } 复制代码

可以发现,当parent的inheritableThreadLocals不为null时,就会将parent的inheritableThreadLocals,赋值给前线程的inheritableThreadLocals。说白了,就是如果当前线程的inheritableThreadLocals不为null,就从父线程哪里拷贝过来一个过来,类似于另外一个ThreadLocal,但是数据从父线程那里来的。有兴趣的小伙伴们可以在去研究研究源码~

8. ThreadLocal的应用场景和使用注意点

ThreadLocal的很重要一个注意点,就是使用完,要手动调用remove()。

而ThreadLocal的应用场景主要有以下这几种:

参考与感谢


作者:捡田螺的小男孩
链接:https://juejin.cn/post/7126708538440679460

上一页123末页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.