ThreadLocal学习心得

一、ThreadLocal是什么

ThreadLocal为线程本地变量,早在JDK 1.2的版本中就提供java.lang.ThreadLocal,其特点为提供了线程内部存储能力,且变量只在本线程中使用,线程之间不共享。

二、ThreadLocal的使用

思考1方法A调用方法B,方法B调用方法C,层层调用,直到调用方法Z,如何将变量X从方法A到方法Z中使用呢?

可以采用的方法有:

①变量X一层层传递,略显麻烦;

②将X设置为静态(static),但多线程同时读写共享资源X时,会产生数据不一致问题;

③将X放入ThreadLocal中,同一线程中,任一方法都可取用X;

 思考2观察下列代码,思考控制台能否打印出“hello A”。

public class ThreadLocalTest {

    static ThreadLocal<String> tl = new ThreadLocal<>();

    public static void main(String[] args) {

        //线程A
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(tl.get());
        }).start();

        //线程B
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tl.set("hello A");
        }).start();
    }
}

结论:控制台打印null,线程A无法get到内容。ThreadLocal为线程本地变量,线程之间彼此隔离。

三、ThreadLocal的实现原理

set方法源码:

    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */

    public void set(T value) {
       //1.获取当前线程
        Thread t = Thread.currentThread();
       //2.将当前线程对象作为key值,传入 getMap() 方法中,最后返回ThreadLocalMap
        ThreadLocalMap map = getMap(t);
       //3.如果map不为null,则以ThreadLocal对象为key,放入ThreadLocal的对象为value,放入到map中
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

接下来我们看第2步,getMap() 方法具体是什么

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

接收到线程后,返回的是线程的成员变量!且类型是ThreadLocalMap。


    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocalMap中是这样描述的:

    static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
       ……
}

可以看到ThreadLocalMap的key(也就是ThreadLocal)是弱引用,会被GC当做垃圾回收掉。回收后ThreadLocalMap的key是null,而value还在,生命周期跟Thread一样长,如果没有手动删除对应key会造成内存泄露

 解决该问题的办法:使用完ThreadLocal后,调用remove方法。

remove方法源码:

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

文章写到这里,基本了解了ThreadLocal的使用,以及为什么能做到存储的变量可以线程之间彼此隔离。本文为自己的学习心得,有不足之处或者需要补充的地方欢迎在评论区交流,大家互相学习,共同进步。

          

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
`ThreadLocal` 是一个 Java 类,用于在多线程环境下为每个线程提供独立的变量副本。通常情况下,在多线程环境下共享变量可能会导致线程安全问题,而 `ThreadLocal` 可以为每个线程提供一个独立的变量副本,从而避免了这个问题。 在使用 `ThreadLocal` 时,每个线程可以通过 `get()` 方法获取到自己的变量副本,而且这个副本只能被当前线程访问和修改。每个线程都有自己独立的变量副本,不会相互干扰。 例如,下面的代码演示了如何使用 `ThreadLocal` 存储和访问一个字符串变量: ``` public class ThreadLocalDemo { private static final ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) { threadLocal.set("Hello, ThreadLocal!"); String value = threadLocal.get(); System.out.println(value); // 输出结果:Hello, ThreadLocal! } } ``` 在上面的代码中,我们定义了一个名为 `threadLocal` 的静态变量,它的类型为 `ThreadLocal<String>`,表示它可以为每个线程提供一个独立的字符串变量。然后在 `main` 方法中,我们通过 `threadLocal.set()` 方法为当前线程设置了一个字符串变量,然后通过 `threadLocal.get()` 方法获取到了这个字符串变量,并输出到控制台上。 需要注意的是,每个线程都需要通过 `get()` 方法获取自己的变量副本,并且在使用完毕后需要及时调用 `remove()` 方法将变量副本从内存中清除,以免造成内存泄漏。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值