深入学习ThreadLocal

1、用来干吗的?

用于线程在任意的地方去共享数据,而不被其他线程所干扰,

2、原理是什么

因为每个线程维护一份ThreadLocalMap,使用threadlocal.set(obj)方法是存放在map里面的Entry<<WeekReference>ThreadLocal,Value>数组里

3、实际案例,比如写了util类,但是SimplateDateFormate是线程不安全的,定义成成员变量多线程调用就会有问题,使用threadlocal相当于每个线程都有一份这个value,也就是simplateDateFormate对象

  

 

 4、为什么不使用thread的id作为Entry的key

当有两个ThreaLocal1和ThreadLocal2时候,在local1设置的值会被loca2中读到,但使用Threadlocal作为key就能区分

5、key为什么会设置弱引用,为什么会内存泄漏

当手动回收了ThreadLocal对象,如果是强引用,那么Entry还有一个对ThreadLocal的强引用,如果不手动删除,会导致这个Entry一直存在

从而导致内存泄漏,当使用弱引用,回收了ThreadLocal对象后,Entry里面是个弱引用,ThreadLocal就会被回收,Entry面的key变成null

在下一次get set remove就会清除掉这些key为null的数据 ,相当于提供了一层保障。

6、使用注意点

使用static修饰threadlocal修饰,当get完调用一次remove清除当此的Entry.

 

附上一个线程泄漏导致oom的例子

VM参数 -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError

package com.xiangwen.day10;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadLocalTest2 {
    private static ThreadLocal<MyThreadLocal> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000));
        for (int i = 0; i < 10; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    long time= Math.round(Math.random()*2000);
                    try {

                        Thread.sleep(time);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    System.out.println(Thread.currentThread().getName() +
                            "休眠结束"+time);
                    MyThreadLocal myThreadLocal = new MyThreadLocal();
                    threadLocal.set(myThreadLocal);
                   // System.gc();
                    //threadLocal.remove();
                }
            });
        }
    }

    static class MyThreadLocal {
        private byte[] bytes = new byte[1 * 1024 * 1024];
    }
}

  

posted @ 2023-06-04 12:34  傲云萧雨  阅读(9)  评论(0编辑  收藏  举报