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

谈一谈Java的ThreadLocal

目录

先说原理:

再上代码:

运行结果:


先说原理:

ThreadLocal 是一个本地线程副本变量工具类,它可以在每个线程中创建一个副本变量,每个线程可以独立地修改自己的副本变量,而不会影响其他线程的副本变量。它的实现原理可以简单概括如下:

  1. ThreadLocal 内部维护了一个 Map 对象,用于存储每个线程的副本变量。Map 的键为线程对象,值为对应线程的副本变量。
  2. 在每个线程中,ThreadLocal 实例会创建一个唯一的 ThreadLocalMap 对象,用于存储该线程的所有副本变量。ThreadLocalMap 是一个自定义的哈希表数据结构继承自 WeakReference,它的键为 ThreadLocal 对象,值为对应线程的副本变量。
  3. 在创建 ThreadLocal 实例时,实际上是在当前线程的 ThreadLocalMap 中新增一个键值对,其中键为当前 ThreadLocal 对象,值为初始化的副本变量。
  4. 当需要获取当前线程的副本变量时,ThreadLocal 实例会先获取当前线程的 ThreadLocalMap,再通过当前 ThreadLocal 对象作为键来获取对应的副本变量。由于每个线程独立维护自己的 ThreadLocalMap,所以不同线程的相同 ThreadLocal 对象对应的副本变量也是不同的。
  5. 当一个线程结束时,它持有的所有 ThreadLocalMap 中的键值对会成为垃圾对象,但由于 ThreadLocalMap 的键是 WeakReference 类型,所以这些键可能被垃圾回收器回收,但值对象不会被回收,从而导致内存泄漏。为了解决这个问题,ThreadLocal 内部使用了 ThreadLocalMapexpungeStaleEntry() 方法,定期清除废弃的键值对。

总的来说,ThreadLocal 通过维护一个 Map,为每个线程创建一个独立的 ThreadLocalMap,并使用弱引用来避免内存泄漏,从而实现了在每个线程中创建独立的副本变量,并提供了线程安全的访问方式。

再上代码:

package cn.net.cdsz.ccb.test;import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;public class test {static class ThreadA implements Runnable {private ThreadLocal<String> threadLocal;public ThreadA(ThreadLocal<String> threadLocal) {this.threadLocal = threadLocal;}@Overridepublic void run() {threadLocal.set("A");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("ThreadA输出:" + threadLocal.get());}}static class ThreadB implements Runnable {private ThreadLocal<String> threadLocal;public ThreadB(ThreadLocal<String> threadLocal) {this.threadLocal = threadLocal;}@Overridepublic void run() {threadLocal.set("B");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("ThreadB输出:" + threadLocal.get());}}public static void main(String[] args) {ThreadLocal<String> threadLocal = new ThreadLocal<>();new Thread(new ThreadA(threadLocal)).start();new Thread(new ThreadB(threadLocal)).start();}}

运行结果:

最常⻅的ThreadLocal使⽤场景为⽤来解决数据库连接、Session管理等。数据库连
接和Session管理涉及多个复杂对象的初始化和关闭。如果在每个线程中声明⼀些
私有变量来进⾏操作,那这个线程就变得不那么“轻量”了,需要频繁的创建和关闭
连接。

http://www.lryc.cn/news/58769.html

相关文章:

  • 边缘检测与阈值分割
  • QQ空间无敌装逼,复制下面的任一代码粘贴即可出现意想不到的图案。
  • 必看!总结5种JavaScript异步解决方案
  • JUC并发编程高级篇第四章之ThreadLocal(人手一份,天下安)
  • dump 定位分析
  • (十二)排序算法-插入排序
  • elasticsearch 认知
  • 《人体地图》笔记
  • java基础集合面试题
  • Vue学习-Vue入门
  • 【项目】bxg基于SaaS的餐掌柜项目实战(2023)
  • 灌区流量监测设备-中小灌区节水改造
  • SpringBoot2核心功能 --- 指标监控
  • python实战应用讲解-【numpy数组篇】常用函数(三)(附python示例代码)
  • DIN论文翻译
  • python列表,元组和字典
  • 300元左右的蓝牙耳机哪个好?300左右音质最好的蓝牙耳机
  • 【消息队列】聊一下生产者消息发送流程
  • 特斯拉和OpenAI的加持,马斯克简直人生赢家
  • 优维低代码:第三方接口接入
  • SQL 177. 第N高的薪水
  • 14天手撸交互式问答数字人直播教程-课程计划
  • spring boot3.0新特性Http客户端远程调用
  • 查询联系:多表查询 - 1
  • 「Bug」OpenCV读取图像为 None 分析
  • EVO——视觉里程计/SLAM轨迹评估工具
  • TCP为什么要三次握手,而不是两次或四次?
  • git 命令:工作日常使用
  • Http和Https
  • 【计算机网络复习】第三章 传输层 2