ThreadLocal是什么?使用场景有哪些?
什么是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是什么?使用场景有哪些?的更多相关文章
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- ThreadLocal概念以及使用场景
ThreadLocal概念以及使用场景 根据自身的知识深度,这里只限于自己使用和学习的知识点整理,原理的解释还需要再沉淀. 该文章从项目开发中举例,希望能帮助到各位,不了解ThreadLocal的朋友 ...
- 聊聊ThreadLocal原理以及使用场景-JAVA 8源码
相信很多人知道ThreadLocal是针对每个线程的,但是其中的原理相信大家不是很清楚,那咱们就一块看一下源码. 首先,我们先看看它的set方法.非常简单,从当前Thread中获取map.那么这个ge ...
- ThreadLocal 原理和使用场景分析
ThreadLocal 不知道大家有没有用过,但至少听说过,今天主要记录一下 ThreadLocal 的原理和使用场景. 使用场景 直接定位到 ThreadLocal 的源码,可以看到源码注释中有很清 ...
- 面试中的 ThreadLocal 原理和使用场景
相信大家不管是在网上做题还是在面试中都经常被问过 ThreadLocal 的原理和用法,虽然一直知道这个东西的存在但是一直没有好好的研究一下原理,没有自己的知识体系.今天花点时间好好学习了一下,分享给 ...
- 简单理解ThreadLocal原理和适用场景
https://blog.csdn.net/qq_36632687/article/details/79551828?utm_source=blogkpcl2 参考文章: 正确理解ThreadLoca ...
- ThreadLocal使用,应用场景,源码实现,内存泄漏
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...
- ThreadLocal应用场景以及源码分析
一.应用篇 ThreadLocal介绍 ThreadLocal如果单纯从字面上理解的话好像是“本地线程”的意思,其实并不是这个意思,只是这个名字起的太容易让人误解了,它的真正的意思是线程本地变量. 实 ...
- ThreadLocal的使用场景分析
目录 一.ThreadLocal介绍 二.使用场景1——数据库事务问题 2.1 问题背景 2.2 方案1-修改接口传参 2.3 方案2-使用ThreadLocal 三.使用场景2——日志追踪问题 四. ...
- 线程本地变量ThreadLocal源码解读
一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...
随机推荐
- Smartbi:用Excel制作移动端的九型人格测试
九型人格是一个近年来倍受美国斯坦福大学等国际著名大学MBA学员推崇并成为现今最热门的课程之一,近十几年来已风行欧美学术界及工商界.全球500强企业的管理阶层均有研习九型性格,并以此培训员工,建立团队 ...
- Smartbi实践:制作可视化分析报表的感悟
估计看到这篇文章的朋友,都是有使用过Smartbi制作数据可视化图表的.但是不是制作过程跟制作效果并没有让自己那么满意.使用过程也经常遇到一些问题解决不了?那是因为你使用的方法不对.你是否在使用Sm ...
- 【vs2019 】调试技巧
在这篇文章中,我们假定读者了解VS基本的调试知识,如: F5 开始使用调试器运行程序 F9 在当前行设置断点 F10 运行到下一个断点处 F5 从被调试的已停止程序恢复执行 F11 步进到函数内(如果 ...
- 【2021新】C#数字格式化字符串
引用来源: https://www.cnblogs.com/flyingbread/archive/2007/01/18/620287.html https://www.cnblogs.com/117 ...
- 常用的一些性能查询sql语句
转至:https://blog.csdn.net/bosschen/article/details/84829912 --查看表锁 select * from sys.v_$sqlarea where ...
- POJ2749 题解
题目大意:有若干牛圈和两个连接起来的的中转点S1,S2.每个牛圈需要选择其中一个中转点与之连接,从而使任意两个牛圈能够连通.有若干对牛圈里的牛互相hate或是互相like.若两个牛圈里的牛互相hate ...
- LeetCode-095-不同的二叉搜索树 II
不同的二叉搜索树 II 题目描述:给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 .可以按 任意顺序 返回答案. 二叉搜索树(Binary ...
- 矩池云 | 新冠肺炎防控:肺炎CT检测
连日来,新型冠状病毒感染的肺炎疫情,牵动的不仅仅是全武汉.全湖北,更是全国人民的心,大家纷纷以自己独特的方式为武汉加油!我们相信坚持下去,终会春暖花开. 今天让我们以简单实用的神经网络模型,来检测肺炎 ...
- Python中的super().__init__()
Python里的super().init()有什么用? 简单的说super().__init__(),就是继承父类的init方法,同样可以使用super()去继承其他方法. 下面是三种不同的继承.调用 ...
- 七天接手react项目 —— state&事件处理&ref
state&事件处理&ref 在 react 起步 一文中,我们学习了 react 相关知识:jsx.组件.props.本篇将继续研究 state.事件处理和ref. state St ...