ThreadLocal面试题总结

ThreadLocal概念

ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。

面试总结

先说Thread,也就是我们的线程类,在这个类里面有一个Map成员变量,源码如下

/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
这个值初始为null。

再看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) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

我们可以看到,先获得当前线程对象,再获得线程对象里的Map,进行设值。
这里再看看这个Map是什么东东
ThreadLocalMap是ThreadLocal类里面的一个静态内部类,这是一个Map结构的类,当然这里并不是探讨数据结构,
你可以简单的把他当成HashMap或者TreeMap(注:千万不要这样对面试官说,我这么说是为了你们更好理解ThreadLocal)
如同所有Map数据结构,里面必然有一个内部类Entry(不懂数据结构的可以去看看TreeMap的内容,初期不用太深入,看看里面大概有几个成员变量就行)
Entry源码:

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

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

我们会发现这个Entry的key在父类里设置super(k),而WeakReference是一个弱引用,即这个key是弱引用
(引用分强软弱虚,平时写的就是强引用,软引用就是当你内存不足的时候gc会删除,弱引用就是每执行gc就会删除,虚引用设计堆外内存暂时不扩展)

这里就有面试点,为什么这个key是弱引用,为什么不用强引用
我们知道gc回收有个可达性算法,当一个东东不被引用就会删除,假如key用强引用即使ThreadLocal不被我们引用了,也还有一个强引用的key拉着这个ThreadLocal让他不被回收,这就是ThreadLocal的第一个内存泄漏
用弱引用就是因为弱引用不像强引用那样,相当于我们不用ThreadLocal了,gc就会吧ThreadLocal给回收

这里面试还会问第二个面试点,即哪怕ThreadLocal被回收了但是Thred线程对象里的Map还在,这就是ThreadLocal的第二个内存泄漏点
那么如何解决呢,其实很简单,不用的k-v,直接调用ThreadLocal的remove()方法就可以了,这样就不会内存泄漏,这点切记要remove

当然还可能有一些2b的问题,为什么Thred线程对象内要用Map
答:一个Thred对象可能不只是对应一个ThreadLocal,可以是多个,这里再看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的key是什么?是this,this是什么,是当前ThreadLocal对象。

顺着这条路看源码再看看csdn别人说的,对照着学习最终才是自己的内容,任何脱离源码的讲解都是扯蛋,哪怕扯得再圆

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
回答: ThreadLocal面试题主要考察对ThreadLocal的理解和使用。ThreadLocal是一种用于解决多线程并发问题的思路,它为每个线程提供了一个独立的变量副本,以避免线程之间的数据共享和竞争问题。在多线程环境下,每个线程通过ThreadLocal来访问自己的变量副本,从而保证了线程之间的数据隔离。 在面试中,可能会考到ThreadLocal的使用场景、使用方法以及其局限性。ThreadLocal的使用场景包括但不限于线程池、web应用中的用户信息存储、数据库连接管理等需要保证线程安全的情况。ThreadLocal的使用方法是通过set方法设置线程的变量副本,通过get方法获取线程的变量副本。需要注意的是,每个线程对应一个ThreadLocal实例,且每个ThreadLocal实例都会创建一个ThreadLocalMap用于存放线程的变量副本。 然而,ThreadLocal也有一些局限性。例如,ThreadLocal只能在当前线程内部共享数据,无法在线程之间共享。另外,由于ThreadLocal的使用需要创建副本,当线程数量很大时,可能会导致内存占用过大。此外,使用ThreadLocal时需要注意内存泄漏的问题,即使用完ThreadLocal后需要及时清理,否则可能会导致内存泄漏。 综上所述,ThreadLocal是一种用于解决多线程并发问题的思路,通过为每个线程提供独立的变量副本来实现线程间的数据隔离。在面试中,可能会问到ThreadLocal的使用场景、使用方法以及其局限性。需要注意的是,ThreadLocal的使用要避免内存泄漏问题,并且在多线程环境下合理使用,以确保线程安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [面试题 - ThreadLocal详解](https://blog.csdn.net/wangnanwlw/article/details/108866086)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [ThreadLocal高频面试题](https://blog.csdn.net/qq_43255017/article/details/126296062)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值