什么是ThreadLocal?

  ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

测试代码:

package com.javaBase.LineDistance;

/**
* 〈一句话功能简述〉;
* 〈功能详细描述〉
*
* @author jxx
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class TestThreadLocal { public static void main(String[] args) { ThreadLocal<Integer> threadLocal = new MyThreadLocal(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
threadLocal.set(threadLocal.get() + 1);
System.out.println("线程1:" + threadLocal.get());
}
}
}); Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
threadLocal.set(threadLocal.get() + 1);
System.out.println("线程2:" + threadLocal.get());
}
}
}); Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
threadLocal.set(threadLocal.get() + 1);
System.out.println("线程3:" + threadLocal.get());
}
}
}); t1.start();
t2.start();
t3.start();
} private static class MyThreadLocal extends ThreadLocal<Integer> { @Override
protected Integer initialValue() {
return 0;
}
} }

执行结果:

线程2:1
线程1:1
线程2:2
线程3:1
线程1:2
线程3:2
线程2:3
线程3:3
线程1:3

有结果可知个线程之间对ThreadLocal的操作互不影响。

ThreadLocal原理

ThreadLocal中的几个主要方法:

  • void set(Object value)设置当前线程的线程局部变量的值。
  • public Object get()该方法返回当前线程所对应的线程局部变量。
  • public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
  • protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

get和set方法源码:

/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
} /**
* 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);
}

  线程隔离的秘密,就在于ThreadLocalMap这个类。ThreadLocalMap是ThreadLocal类的一个静态内部类,它实现了键值对的设置和获取(对比Map对象来理解),每个线程中都有一个独立的ThreadLocalMap副本,它所存储的值,只能被当前线程读取和修改。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。还有一点就是,ThreadLocalMap存储的键值对中的键是this对象指向的ThreadLocal对象,而值就是你所设置的对象了。

ThreadLocal的应用场景

1、方便同一个线程使用某一对象,避免不必要的参数传递;
2、线程间数据隔离(每个线程在自己线程里使用自己的局部变量,各线程间的ThreadLocal对象互不影响);
3、获取数据库连接、Session、关联ID(比如日志的uniqueID,方便串起多个日志);
其中spring中的事务管理器就是使用的ThreadLocal:
  Spring的事务管理器通过AOP切入业务代码,在进入业务代码前,会依据相应的事务管理器提取出相应的事务对象,假如事务管理器是DataSourceTransactionManager,
就会从DataSource中获取一个连接对象,通过一定的包装后将其保存在ThreadLocal中。而且Spring也将DataSource进行了包装,重写了当中的getConnection()方法,或者说
该方法的返回将由Spring来控制,这样Spring就能让线程内多次获取到的Connection对象是同一个。

参考链接:彻底理解ThreadLocal

       java ThreadLocal(应用场景及使用方式及原理)

ThreadLocal是什么?使用场景有哪些?的更多相关文章

  1. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  2. ThreadLocal概念以及使用场景

    ThreadLocal概念以及使用场景 根据自身的知识深度,这里只限于自己使用和学习的知识点整理,原理的解释还需要再沉淀. 该文章从项目开发中举例,希望能帮助到各位,不了解ThreadLocal的朋友 ...

  3. 聊聊ThreadLocal原理以及使用场景-JAVA 8源码

    相信很多人知道ThreadLocal是针对每个线程的,但是其中的原理相信大家不是很清楚,那咱们就一块看一下源码. 首先,我们先看看它的set方法.非常简单,从当前Thread中获取map.那么这个ge ...

  4. ThreadLocal 原理和使用场景分析

    ThreadLocal 不知道大家有没有用过,但至少听说过,今天主要记录一下 ThreadLocal 的原理和使用场景. 使用场景 直接定位到 ThreadLocal 的源码,可以看到源码注释中有很清 ...

  5. 面试中的 ThreadLocal 原理和使用场景

    相信大家不管是在网上做题还是在面试中都经常被问过 ThreadLocal 的原理和用法,虽然一直知道这个东西的存在但是一直没有好好的研究一下原理,没有自己的知识体系.今天花点时间好好学习了一下,分享给 ...

  6. 简单理解ThreadLocal原理和适用场景

    https://blog.csdn.net/qq_36632687/article/details/79551828?utm_source=blogkpcl2 参考文章: 正确理解ThreadLoca ...

  7. ThreadLocal使用,应用场景,源码实现,内存泄漏

    首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...

  8. ThreadLocal应用场景以及源码分析

    一.应用篇 ThreadLocal介绍 ThreadLocal如果单纯从字面上理解的话好像是“本地线程”的意思,其实并不是这个意思,只是这个名字起的太容易让人误解了,它的真正的意思是线程本地变量. 实 ...

  9. ThreadLocal的使用场景分析

    目录 一.ThreadLocal介绍 二.使用场景1——数据库事务问题 2.1 问题背景 2.2 方案1-修改接口传参 2.3 方案2-使用ThreadLocal 三.使用场景2——日志追踪问题 四. ...

  10. 线程本地变量ThreadLocal源码解读

      一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...

随机推荐

  1. [题解]第十一届北航程序设计竞赛预赛——H.高中数学题

    题目描述 解题思路 可以求得通项公式:an = 2n + 1,所以问题就变成等差数列求异或和,这个具体为什么对我还不能很好地解释清楚,先挖坑吧. 附:c++代码 1 #include <iost ...

  2. Delegate 委托细说

    目录 委托的申明 委托的赋值 委托实例方法的使用C#Invoke\BeginInvoke\Endinoke  系统自带的委托Action.Action<T>.Func<T>.P ...

  3. linux时钟校准

    ## 查看系统时间 date ## 查看硬件时间 hwclock ## 手动设置时间 date -s "20210507 17:55:00" ## 同步硬件时间 hwclock - ...

  4. ImageNet2017文件介绍及使用

    ImageNet2017文件介绍及使用 文件说明 imagenet_object_localization.tar.gz包含训练集和验证集的图像数据和地面实况,以及测试集的图像数据. 图像注释以PAS ...

  5. windows下cuda、cudnn以及pytorch的安装

    一.在anaconda下配置cuda.cudnn以及pytorch环境 1.打开Anaconda Prompt,输入 conda create -n pytorch python=3.8        ...

  6. SpringBoot进阶教程(七十三)整合elasticsearch

    Elasticsearch 是一个分布式.高扩展.高实时的搜索与数据分析引擎.它能很方便的使大量数据具有搜索.分析和探索的能力.充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更 ...

  7. Python:GUI库tkinter(三)

    这一章是对前两章的总结: Python:GUI库tkinter(一) Python:GUI库tkinter(二) 前两章是对控件的介绍,第一章可以知道各控件使用时的具体参数,第二章以具体的例子展示了每 ...

  8. 矩池云助力科研算力免费上"云",让 AI 教学简单起来

    矩池云是一个专业的国内深度学习云平台,拥有着良好的深度学习云端训练体验,和高性价比的GPU集群资源.而且对同学们比较友好,会经常做一些大折扣的活动,最近双十一,全场所有的RTX 2070.Platin ...

  9. Redis集群-Cluster模式

    我理解的此模式与哨兵模式根本区别: 哨兵模式采用主从复制模式,主和从数据都是一致的.全量数据: Cluster模式采用数据分片存储,对每个 key 计算 CRC16 值,然后对 16384 取模,可以 ...

  10. tp6微信公众号开发者模式token认证

      微信公众号开发完整教程(一) PHP7.0版本,TP5.0框架 技术标签: 微信公众号开发         因为工作的需要,这一两年对微信公众号和小程序,项目制作的比较多.所以我才打算写一篇全面的 ...