当前位置: 首页 > wzjs >正文

深圳html5网站建设seo搜索引擎官网

深圳html5网站建设,seo搜索引擎官网,学校网站建设 效果,展示型网站与营销型网站区别ThreadLocal也是面试题中十分常见的问题,我是在大部分人的启蒙项目苍穹外卖接触到ThreadLocal这个概念的,苍穹外卖把用户id存在ThreadLocal中来进行权限检验,这是我所了解到的ThreadLocal的第一个用处。 在上次字节面试时被面试官狠狠拷打了…

ThreadLocal也是面试题中十分常见的问题,我是在大部分人的启蒙项目苍穹外卖接触到ThreadLocal这个概念的,苍穹外卖把用户id存在ThreadLocal中来进行权限检验,这是我所了解到的ThreadLocal的第一个用处。

在上次字节面试时被面试官狠狠拷打了ThreadLocal,从概念问到了底层,而我只背了八股,了解到ThreadLocal底层是个map,有弱引用,在面试官反复的反问上败下阵来,今天又是我一个小实习生摸鱼的一天,决定看一看ThreadLocal源码,看一看他到底是何方神圣。

ThreadLocal简介

ThreadLocal 是 Java 中用于实现线程局部变量的类,它能够在多线程环境下,为每个线程提供独立的变量副本,从而避免线程间的数据竞争。

核心作用

  • 线程隔离:每个线程操作自己的变量副本,互不干扰。

  • 避免同步:不需要加锁(如 synchronizedsynchronized),提高并发性能。

  • 典型应用

    • Spring 的事务管理(TransactionSynchronizationManager)

    • 用户会话信息存储(如 Session)

    • JDBC 连接管理(避免线程间共享Connection)

ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。

 ThreadLocal原理

 ThreadLocal的set()方法

public void set(T value) {Thread t = Thread.currentThread();  // 获取当前线程ThreadLocalMap map = getMap(t);     // 获取线程的 ThreadLocalMapif (map != null) {map.set(this, value);  // 如果 map 已存在,直接设置值} else {createMap(t, value);   // 否则初始化 ThreadLocalMap}
}

 从上面的代码可以看出,ThreadLocal  set赋值的时候首先会获取当前线程thread,并获取thread线程中的ThreadLocalMap属性。如果map属性不为空,则直接更新value值,如果map为空,则实例化threadLocalMap,并将value值初始化。

那么第二个问题来了,ThreadLocalMap是什么?

ThreadLocalMap实现

static class ThreadLocalMap {/*** The entries in this hash map extend WeakReference, using* its main ref field as the key (which is always a* ThreadLocal object).  Note that null keys (i.e. entry.get()* == null) mean that the key is no longer referenced, so the* entry can be expunged from table.  Such entries are referred to* as "stale entries" in the code that follows.*/static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}}

可看出ThreadLocalMap是ThreadLocal的内部静态类,用于存储线程的局部变量,而它的构成主要是用Entry来保存数据 ,而且还是继承的弱引用(常用考点)。在Entry内部使用ThreadLocal作为key,使用我们设置的value作为value。每个线程都有一个独立的 ThreadLocalMap,存储该线程的所有 ThreadLocal 变量。

ThreadLocalMap的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)]) {if (e.refersTo(key)) {  // 如果 key 已存在,更新 valuee.value = value;return;}if (e.refersTo(null)) {  // 如果 key 已被回收(弱引用),替换过期 EntryreplaceStaleEntry(key, value, i);return;}}tab[i] = new Entry(key, value);  // 插入新 Entryint sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold) {rehash();  // 扩容}
}

ThreadLocalMap的getEntry()方法

private Entry getEntry(ThreadLocal<?> key) {int i = key.threadLocalHashCode & (table.length - 1);Entry e = table[i];if (e != null && e.get() == key) {return e;  // 直接命中} else {return getEntryAfterMiss(key, i, e);  // 线性探测查找}
}

ThreadLocal的get()方法

public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);  // 获取当前 ThreadLocal 对应的 Entryif (e != null) {@SuppressWarnings("unchecked")T result = (T) e.value;return result;}}return setInitialValue();  // 如果不存在,初始化并返回默认值
}private T setInitialValue() {T value = initialValue();  // 默认返回 null,可重写Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}return value;
}

ThreadLocal的remove()方法

public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null) {m.remove(this);  // 从 ThreadLocalMap 中移除当前 ThreadLocal}
}

调用 remove() 方法会直接从当前线程的 ThreadLocalMap 中删除对应的 ThreadLocal 键值对。这一操作的核心目的是防止内存泄漏。

ThreadLocal 的内存泄漏问题

ThreadLocalMap使用 ThreadLocal的弱引用作为 key,弱引用的特性是:如果某个对象仅被弱引用关联,垃圾回收(GC)时会自动清理该对象。因此,如果 ThreadLocal未被外部强引用持有,GC 时会回收 ThreadLocal实例,导致 ThreadLocalMap中的 key 变为 null。

然而,ThreadLocalMap中的 value 仍然是强引用,即使 key 被回收,value 也不会被自动清理。这会导致 ThreadLocalMap中存在大量 key 为 null但 value 仍占用内存的条目,从而引发内存泄漏。

线程复用与内存泄漏的关联

ThreadLocal的变量生命周期与线程绑定。在线程池场景下,线程通常会被复用,导致线程的生命周期可能极长(甚至与 JVM 生命周期一致)。如果未及时清理 ThreadLocal变量(如未调用 remove() 或替换值),其存储的数据会一直堆积。

ThreadLocal与Thread,ThreadLocalMap的关系

图片来自于史上最全ThreadLocal 详解(一)-CSDN博客。从图中可以看出三者之间的关系。

关于ThreadLocal的常见面试题

4.1 ThreadLocal 和 synchronized 的区别?

对比项ThreadLocalsynchronized
数据隔离方式每个线程独立副本共享数据 + 锁
性能无锁,更高性能有锁,可能阻塞
适用场景线程隔离数据(如 Session)线程共享数据(如计数器)

4.2 ThreadLocal 的 key 为什么是弱引用?

  • 防止内存泄漏

    • 如果 ThreadLocal被回收,Entry 的 key 会自动被 GC 清理,避免 ThreadLocal无法回收。

  • 但 value 仍需手动清理

    • 因为 value 是强引用,需要 remove() 或 set(null)。

4.3 ThreadLocal 的 key 为什么不设为强引用?

在业务代码中使用完ThreadLocal后,即使ThreadLocal引用被回收,由于ThreadLocalMap的Entry强引用了ThreadLocal(ThreadLocal作为key),导致ThreadLocal对象无法被回收。当没有手动删除Entry且当前线程仍在运行时,会形成一条强引用链:当前线程引用→当前线程→ThreadLocalMap→Entry。这个Entry包含了ThreadLocal实例和value,因此不会被回收,从而造成内存泄漏。换言之,由于ThreadLocalMap的key采用强引用机制,内存泄漏问题无法完全避免。

以上就是关于ThreadLocal的一些解析与想法。

http://www.dtcms.com/wzjs/502650.html

相关文章:

  • 做淘宝客网站能有效果吗重大新闻事件
  • 网站改关键词指数函数图像
  • 中山 网站建设媒体发稿费用
  • 做h的小说网站有哪些小程序开发公司十大排名
  • p2p网站建设报价seo最好的工具
  • .net 大型网站开发百度搜索名字排名优化
  • 微网站是用什么代码制作网站提交入口百度
  • 网站建设实施方案ppt手机app免费制作平台
  • 教育网站报名免费淘宝关键词工具
  • 政府网站建设总体情况网站备案查询官网
  • 做网站被骗了怎么办想建立自己的网站怎么建立
  • 海外建站服务平台备案查询网
  • win7在局域网做网站考拉seo
  • 小视频解析网站怎么做曲靖seo建站
  • 锦州网站建设信息淘宝seo优化是什么
  • 廊坊哪里有做网站建设的佛山竞价账户托管
  • 微信网站系统网络管理系统
  • 除了外链 还有什么办法使网站提高排名广丰网站seo
  • 做网站为什么要去工厂关键词挖掘排名
  • 中国寰球工程有限公司网站设计湖南网络推广排名
  • 抚州网站建设免费职业技能培训网
  • 公司网站没有备案是不是违法的腾讯推广一次广告多少钱
  • 移动端处理器天梯图百度网站怎么优化排名靠前
  • 做外贸有哪些网站比较好产品推广计划书怎么写
  • 网站建设新闻发布注意什么百度广告优化
  • 建设电子商务网站要多少钱竞价排名广告
  • 如何做网站优化seo百度app官方下载安装
  • 长沙建网站设计甘肃省seo关键词优化
  • 网站建设河南百度收录入口
  • wordpress 媒体库代码aso优化什么意思是