热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaThreadLocal使用和源码分析

文章目录ThreadLocal使用和源码分析概述基本使用源码分析ThreadThreadLocalThreadLocalMap内存泄漏问题ThreadLocal使用和源码分析概述


文章目录

  • ThreadLocal使用和源码分析
    • 概述
    • 基本使用
    • 源码分析
      • Thread
      • ThreadLocal
      • ThreadLocalMap
    • 内存泄漏问题


ThreadLocal使用和源码分析


概述


  • ThreadLocal即线程局部变量。
  • ThreadLocal提供线程的局部变量,每个线程可以通过了get/set方法对局部变量进行操作。
  • 局部变量不会和其他线程的局部变量有冲突,实现了线程的数据隔离。
  • Thread和ThreadLocal关系:
    • Thread内部持有ThreadLocalMap类型的成员变量threadLocals。
    • ThreadLocal是负责操作线程局部变量的管理类,有get()、set()、remove()方法负责获取、设置、清除数据。
    • ThreadLocalMap是ThreadLocal的内部类,用于存储线程的局部变量,内部维护一个Entry数组,键值对结构,键为ThreadLocal类型,值为Object类型。

在这里插入图片描述

在这里插入图片描述


基本使用

//创建ThreadLocal对象
private static ThreadLocal<String> mThreadLocal &#61; new ThreadLocal<>();static class A implements Runnable {&#64;Overridepublic void run() {//设置数据mThreadLocal.set("线程A");//覆盖数据mThreadLocal.set("线程AAA");//获取数据System.out.println(mThreadLocal.get());}
}static class B implements Runnable {&#64;Overridepublic void run() {mThreadLocal.set("线程B");System.out.println(mThreadLocal.get());}
}public static void main(String[] args) {mThreadLocal.set("线程main");new Thread(new A()).start();new Thread(new B()).start();System.out.println(mThreadLocal.get());
}

输出信息&#xff1a;

线程main
线程AAA
线程B

源码分析


Thread

public class Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals &#61; null;private void exit() { threadLocals &#61; null;}
}

ThreadLocal

public class ThreadLocal<T> {//创建ThreadLocalMap对象void createMap(Thread t, T firstValue) {t.threadLocals &#61; new ThreadLocalMap(this, firstValue);}//获取ThreadLocalMap对象ThreadLocalMap getMap(Thread t) {return t.threadLocals;}//设置ThreadLocal变量的值//获取当前线程&#xff0c;再获取ThreadLocalMap对象&#xff0c;如果map不为null进行set操作&#xff0c;map为null则进行创建操作public void set(T value) {Thread t &#61; Thread.currentThread();ThreadLocalMap map &#61; getMap(t);if (map !&#61; null)map.set(this, value);elsecreateMap(t, value);}//获取ThreadLocal变量的值public T get() {Thread t &#61; Thread.currentThread();ThreadLocalMap map &#61; getMap(t);if (map !&#61; null) {ThreadLocalMap.Entry e &#61; map.getEntry(this);if (e !&#61; null) {T result &#61; (T)e.value;return result;}}return setInitialValue();}//初始化ThreadLocal的值private T setInitialValue() {T value &#61; initialValue();Thread t &#61; Thread.currentThread();ThreadLocalMap map &#61; getMap(t);if (map !&#61; null)map.set(this, value);else//创建createMap(t, value);return value;}//清除数据public void remove() {ThreadLocalMap m &#61; getMap(Thread.currentThread());if (m !&#61; null)m.remove(this);}private void remove(ThreadLocal<?> key) {Entry[] tab &#61; table;int len &#61; tab.length;int i &#61; key.threadLocalHashCode & (len-1);for (Entry e &#61; tab[i];e !&#61; null;e &#61; tab[i &#61; nextIndex(i, len)]) {if (e.get() &#61;&#61; key) {e.clear();expungeStaleEntry(i);return;}}}
}

ThreadLocalMap

static class ThreadLocalMap {//存储数据static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value &#61; v;}}//table初始容量private static final int INITIAL_CAPACITY &#61; 16;//table用于存储数据private Entry[] table;//下次扩容的阀值private int threshold; //2/3的负载因子private void setThreshold(int len) {threshold &#61; len * 2 / 3;}//初始化ThreadLocalMap&#xff0c;key为ThreadLocalThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table &#61; new Entry[INITIAL_CAPACITY];int i &#61; firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] &#61; new Entry(firstKey, firstValue);size &#61; 1;setThreshold(INITIAL_CAPACITY);}//设置数据private void set(ThreadLocal<?> key, Object value) { Entry[] tab &#61; table;int len &#61; tab.length;//通过hash值获取索引值int i &#61; key.threadLocalHashCode & (len-1);//遍历tab如果存在则更新for (Entry e &#61; tab[i];e !&#61; null;e &#61; tab[i &#61; nextIndex(i, len)]) {ThreadLocal<?> k &#61; e.get();//key相同&#xff0c;覆盖值if (k &#61;&#61; key) {e.value &#61; value;return;}//key为null&#xff0c;清空所有key为null的数据if (k &#61;&#61; null) {replaceStaleEntry(key, value, i);return;}}//若不存在则直接添加tab[i] &#61; new Entry(key, value);int sz &#61; &#43;&#43;size;if (!cleanSomeSlots(i, sz) && sz >&#61; threshold)rehash();}//获取数据private Entry getEntry(ThreadLocal<?> key) {int i &#61; key.threadLocalHashCode & (table.length - 1);Entry e &#61; table[i];if (e !&#61; null && e.get() &#61;&#61; key)return e;elsereturn getEntryAfterMiss(key, i, e);}
}

内存泄漏问题

ThreadLocalMap内部维护了一个Entry数组&#xff0c;在没有执行remove的情况下&#xff0c;将ThreadLocal设置为null&#xff0c;下次GC时&#xff0c;key是弱引用会被回收&#xff0c;value是强引用并指向对象就会一直存在内存中&#xff0c;这样会发生内存泄露。

所以ThreadLocal使用后需要及时remove掉。


推荐阅读
  • 浅析Java泛型及其应用
    Java泛型是自JDK 5引入的一项重要特性,旨在增强代码的类型安全性和复用性。通过泛型,开发人员可以在编译阶段进行类型检查,有效避免运行时的类型转换错误。本文将探讨Java泛型的基本概念、实现机制及其在实际开发中的应用场景,帮助读者深入理解并灵活运用这一强大工具。 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 本文详细探讨了OpenCV中人脸检测算法的实现原理与代码结构。通过分析核心函数和关键步骤,揭示了OpenCV如何高效地进行人脸检测。文章不仅提供了代码示例,还深入解释了算法背后的数学模型和优化技巧,为开发者提供了全面的理解和实用的参考。 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • Eclipse JFace Text框架中IDocument接口的getNumberOfLines方法详解与编程实例 ... [详细]
  • 如何在 Node.js 环境中将 CSV 数据转换为标准的 JSON 文件格式? ... [详细]
  • 本文作为《Java学习笔记》的开篇,旨在为初学者提供一个全面的概览。文章首先介绍了Java的基本概念及其在编程语言中的地位,强调了Java与其他主流编程语言的共通之处,特别是其核心结构,如控制语句的重要性。通过详细的目录和前言,读者可以快速了解Java的基础知识和学习路径。此外,文章还探讨了控制语句在编程中的关键作用,为后续深入学习打下坚实基础。 ... [详细]
  • 本次发布的Qt音乐播放器2.0版本在用户界面方面进行了细致优化,提升了整体的视觉效果和用户体验。尽管核心功能与1.0版本保持一致,但界面的改进使得操作更加直观便捷,为用户带来了更为流畅的使用体验。此外,我们还对部分细节进行了微调,以确保软件的稳定性和性能得到进一步提升。 ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • 在Java编程中,为了提高代码的可读性和执行效率,建议优先使用局部变量来存储方法的返回值,而不是多次调用同一个方法。这样不仅可以减少方法调用的开销,还能避免潜在的性能问题。此外,使用局部变量还可以增强代码的可维护性和调试便利性。 ... [详细]
  • 我正在使用 Ruby on Rails 构建个人网站。总体而言,RoR 是一个非常出色的工具,它提供了丰富的功能和灵活性,使得创建自定义页面变得既高效又便捷。通过利用其强大的框架和模块化设计,我可以轻松实现复杂的功能,同时保持代码的整洁和可维护性。此外,Rails 的社区支持也非常强大,为开发过程中遇到的问题提供了丰富的资源和解决方案。 ... [详细]
  • 使用 MyEclipse 和 TestNG 测试框架在 Java 中高效进行单元测试
    通过MyEclipse集成TestNG测试框架,可以在Java开发中高效地进行单元测试。本文介绍了在JDK 1.8.0_121和MyEclipse 10.0离线环境下配置和使用TestNG的具体步骤,帮助开发者提高测试效率和代码质量。 ... [详细]
  • 开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用
    开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用 ... [详细]
  • 在开发系统查询搜索功能时,需注意以下几点以提高信息检索效率:首先,在SQL语句中,每个参数占位符“?”后必须紧跟相应的参数赋值,确保参数与赋值一一对应,避免因参数不匹配导致的错误。其次,进行模糊搜索时,若用户输入通配符“%”,可能会导致全表扫描,因此需要对输入的“%”进行特殊处理或限制,以防止不必要的性能开销。此外,建议使用索引优化查询速度,并合理设计搜索逻辑,以提升用户体验。 ... [详细]
author-avatar
神秘的霸气沉默_168
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有