所以平时我们线程使用完销毁是不会有有内存泄漏问题的
那么网上一直流传的内存泄漏问题是否真的存在呢?其实是存在的 。大家想想我们平时在做项目的时候自己创建线程的场景多吗?很明显基本没有,因为线程的创建销毁代价太过昂贵,我们一般都是使用线程池,那么问题来了,线程池的线程一般会循环利用,不会销毁 。所以网上说的内存泄漏是发生在使用线程池的场景
再谈弱引用问题
我们首先来看看的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一个属性,然后我们看看
方法
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) {e.value = http://www.kingceram.com/post/value;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();}
我们看新加值的关键代码
tab[i] = new Entry(key, value);
可以看到Entry的key 就是我们的,在看Entry的定义
static class Entry extends WeakReference> {}
这里就看到了我们说的弱引用,即Entry的key是对的弱引用,那么现在的引用状态呢,这里借鉴网上的一张图:
可以很清晰的看到Entry对的弱引用 。
注意这里弱引用解决的问题:首先虽然Key是对,但是key并不会被回收,因为线程对他是强引用,这里解决的问题是为了防止自身的内存泄漏,因为如果这里key对是强引用,那么在我们将栈中的变量不指向,也无法被回收,因为还有key对他是一个强引用,如果这是弱引用,就可以顺利被回收
弱引用:使用修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收
这里证明比较复杂,但我还是引用网上的一段代码去证明
首先证明key 被回收的场景
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException {Thread t = new Thread(()->test("abc",false));t.start();t.join();System.out.println("--gc后--");Thread t2 = new Thread(() -> test("def", true));t2.start();t2.join();}private static void test(String s,boolean isGC){try {new ThreadLocal<>().set(s);if (isGC) {System.gc();}Thread t = Thread.currentThread();Class extends Thread> clz = t.getClass();Field field = clz.getDeclaredField("threadLocals");field.setAccessible(true);Object ThreadLocalMap = field.get(t);Class> tlmClass = ThreadLocalMap.getClass();Field tableField = tlmClass.getDeclaredField("table");tableField.setAccessible(true);Object[] arr = (Object[]) tableField.get(ThreadLocalMap);for (Object o : arr) {if (o != null) {Class> entryClass = o.getClass();Field valueField = entryClass.getDeclaredField("value");Field referenceField = entryClass.getSuperclass().getSuperclass().getDeclaredField("referent");valueField.setAccessible(true);referenceField.setAccessible(true);System.out.println(String.format("弱引用key:%s,值:%s", referenceField.get(o), valueField.get(o)));}}} catch (Exception e) {e.printStackTrace();}}
输出结果:
弱引用key:java.lang.ThreadLocal@433619b6,值:abc弱引用key:java.lang.ThreadLocal@418a15e3,值:java.lang.ref.SoftReference@bf97a12--gc后--弱引用key:null,值:def
- 日本大妈打破吉尼斯世界纪录,92岁仍旧在工作,真的太拼了! 日本吉尼斯记录节目
- 揭密:隋炀帝真的是无恶不作的暴君?
- 历史上康熙的良妃真的不受宠爱吗?
- 《最本真的最美味》:最美味的食物往往从心 世界之最英文书名是什么
- 次世代的火热不是捧出来的,次世代角色建模工作真的有前途吗?
- 数羊真的可以帮助入眠吗 数羊真的有助于睡觉吗
- 传说中的四维生物,古代有人专门饲养,龙是否真实存在? 历史上有龙之最吗
- 历史上秦始皇身世揭秘:父亲真的是珠宝商人
- 字节月薪50K测试主管,总结的2023年测试人跳槽建议,不注意这些真的要吃亏
- 20架运20排排坐,我以为照片是P的,结果竟然是真的 运20吉尼斯记录