美文网首页
对于ThreadLocal的理解

对于ThreadLocal的理解

作者: 倚仗听江 | 来源:发表于2020-09-07 09:39 被阅读0次

ThreadLocal叫线程本地变量,他为每个线程都创建了一个副本变量,每个线程都只能访问自己的副本变量。

作用:让线程自己独立保存一份自己的变量副本(多线程情况下变量安全的一种解决思路)
使用场景:当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候。

每个线程都有一个ThreadLocalMap的实例对象,并且通过ThreadLocal管理ThreadLocalMap。

public T get() {
    //获取当前线程
    Thread t = Thread.currentThread();
    //获取当前线程的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        //this是当前的ThreadLocalMap(key),getEntry通过key拿到value
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

内存泄漏问题:
首先先注意ThreadLocal 使用弱引用是为了预防内存泄漏的。 ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,弱引用的特点是,如果这个对象只存在弱引用,那么在下一次垃圾回收的时候必然会被清理掉。假设我们创建一个ThreadLocal 对象:ThreadLocal tl = new ThreadLocal ();并调用set方法。我们先来看一下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);
    }

可以发现,map.set(this, value);map的key是this,而this就是ThreadLocal对象。那假设现在我们不想使用这个tl对象了,把它设置为null。但map中的key始终指向着这个tl对象,也就发生了内存泄漏。

static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

所以如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候会被清理掉的,这样一来 ThreadLocalMap中使用这个 ThreadLocal 的 key 也会被清理掉。但是,value 是强引用,不会被清理,这样一来就会出现 key 为 null 的 value。

ThreadLocalMap实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。如果说会出现内存泄漏,那只有在出现了 key 为 null 的记录后,没有手动调用 remove() 方法,并且之后也不再调用 get()、set()、remove() 方法的情况下。

使用示例:

public class ThreadLocalTest {

    public static void main(String[] args) {
        final ThreadLocal<String> threadLocal1 = new ThreadLocal<>();
        final ThreadLocal<Integer> threadLocal2 = new ThreadLocal<>();

        new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal1.set("A");
                threadLocal2.set(1);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
                System.out.println(threadLocal1.get());
                System.out.println(threadLocal2.get());
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal1.set("B");
                threadLocal2.set(2);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
                System.out.println(threadLocal1.get());
                System.out.println(threadLocal2.get());
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
                System.out.println(threadLocal1.get());
                System.out.println(threadLocal2.get());
            }
        }).start();
    }
}

输出为:

Thread-2
null
null
Thread-0
A
1
Thread-1
B
2

可以看到对数据存储后,只有在线程中才可以获取到存储的数据,对于其他线程来说是无法获取到数据。

相关文章

  • 对于ThreadLocal的理解

    ThreadLocal叫线程本地变量,他为每个线程都创建了一个副本变量,每个线程都只能访问自己的副本变量。 作用:...

  • 深入理解 ThreadLocal (这些细节不应忽略)

    前言 对于 ThreadLocal 的使用,并不难。但要深入理解 ThreadLocal 的实现方式,需要细细揣摩...

  • 线程的深入理解(三):ThreadLocal深入理解

    前言 对于 ThreadLocal 的使用,并不难。但要深入理解 ThreadLocal 的实现方式,需要细细揣摩...

  • ThreadLocal

    理解ThreadLocal 理解ThreadLocal的关键在于理解 Thread, threadLocals, ...

  • ThreadLocal的使用事例

    列举几个使用ThreadLocal的事例,能更好的理解ThreadLocal。 1、运用ThreadLocal实现...

  • 14-ThreadLocal类详细剖析

    ThreadLocal类详细剖析 对ThreadLocal的理解 JDK中的源码是这样描述ThreadLocal的...

  • ThreadLocal 深度解析

    一.对ThreadLocal的理解二.深入解析ThreadLocal类三.ThreadLocal的应用场景 对Th...

  • ThreadLocal源码分析

    1.对ThreadLocal的理解 ThreadLocal是一个创建线程局部量的类。使用ThreadLocal创建...

  • ThreadLocal-jdk1.8

    ThreadLocal的用处 对于每一个ThreadLocal实例对象,每个线程往这个ThreadLocal中读写...

  • ThreadLocal的理解

    老板提了一个需求,需要我们在某个类中增加一个String成员变量name,好的,没问题 然后老板又提了一个需求,需...

网友评论

      本文标题:对于ThreadLocal的理解

      本文链接:https://www.haomeiwen.com/subject/omrkektx.html