一、ThreadLocal基本使用

1.1使用场景

不同的线程对全局变量进行修改,使用ThreadLocal后会为每个线程创建一个副本,而不会影响其他线程的副本,确保了线程的安全

  private static ThreadLocal<Integer> localvariable=ThreadLocal.withInitial(()->1);
public static void main(String[] args) {
Thread threadOne=new Thread(new Runnable() {
@Override
public void run() {
Integer integer = localvariable.get();
localvariable.set(++integer);
System.out.println("线程1: "+localvariable.get());
}
});
Thread threadTwo=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程2: "+localvariable.get());
}
});
System.out.println("主线程: "+localvariable.get());
threadOne.start();
threadTwo.start();
}

运行结果:

主线程: 1
线程1: 2
线程2: 1

线程1的修改没有影响到线程2的读取,保证了线程的安全

场景二

类似于全局变量,但是不想被多个线程进行共享

    private static Integer count=0;
private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
for(int i=0;i<10;i++){
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println(count);
}
};
fixedThreadPool.execute(runnable);
}
count++;
}

像如上代码,本来是想所有线程都输出初始的count,当主线程累加后,剩下的线程输出的值就变成了1

以上代码执行的结果:

0
0
0
0
1
1
1
1
1
1

那么我们可以用ThreadLocal将原始的全局变量进行保存然后传参给其他的线程,这样就获取的是原始的全局变量

 private static Integer count=0;
private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
private static ThreadLocal<Integer> local=new ThreadLocal();
public static void main(String[] args) {
local.set(count);
for(int i=0;i<10;i++){
Integer localCount = local.get();
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println(localCount);
}
};
fixedThreadPool.execute(runnable);
}
count++;
}

0
0
0
0
0
0
0
0
0
0

1.2 原理分析

threadLocals = null;
inheritableThreadLocals = null;

Thread类中有一个threadLocals和一个inheritableThreadLocals,他们都是ThreadLocalMap 类型的变量,默认都为null

当第一次调用set方法的时候创建

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

将每个线程的本地变量存放在threadLocals变量中,如果调用线程一直不终止,那么这个本地变量会一直存放在调用线程的ThreadLocals变量里面,所以当不使用本地变量是可以通过调用ThreadLocal变量的remove方法,从当前线程的threadLocals

里面删除该本地变量。

ThreadLocal 是JDK 包提供的,它提供了线程本地变量,也就是如果你创建了一个
ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的一个本地副本。当多
个线程操作这个变量时,实际操作的是自己本地内存里面的变量,从而避免了线程安全问

ThreadLocal使用总结的更多相关文章

  1. ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...

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

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

  3. Threadlocal使用Case

    Threadlocal能够为每个线程分配一份单独的副本,使的线程与线程之间能够独立的访问各自副本.Threadlocal 内部维护一个Map,key为线程的名字,value为对应操作的副本. /** ...

  4. 多线程映射工具——ThreadLocal

    ThreadLocal相当于一个Map<Thread, T>,各线程使用自己的线程对象Thread.currentThread()作为键存取数据,但ThreadLocal实际上是一个包装了 ...

  5. ThreadLocal 工作原理、部分源码分析

    1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...

  6. ThreadLocal<T>的是否有设计问题

    一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...

  7. 理解ThreadLocal —— 一个map的key

    作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...

  8. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  9. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  10. ThreadLocal 源码剖析

    ThreadLocal是Java语言提供的用于支持线程局部变量的类.所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量(每个线程一个拷贝).在各个Java web的各种框架 ...

随机推荐

  1. Springboot使用EasyExcel(仅限自己收藏)

    pom文件依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel< ...

  2. 通过RayFire为图形添加二次破碎效果

    在完成3D建模之后,RayFire能帮助用户制作多种类型的破碎效果,如均匀碎片.放射状碎片.木碎等效果.另外,用户还可以利用RayFire的碎片选取功能,为图形进行二次破碎,以达到增加局部碎片的效果. ...

  3. mac中怎么完成移动硬盘分区这个操作

    移动硬盘在出厂时只有一个区,不方便我们存储和查阅文件,移动硬盘分区可以防止硬盘发生错误,以免造成资料丢失,也可以防止产生无用文件. 移动硬盘基本上都是用Windows系统进行分区的,但是现在很多人使用 ...

  4. mathtype样式系统使用技巧-通过样式定义来更改方程中的字体

    本教程中,我们主要介绍MathType Desktop的样式系统.演示如何通过更改样式定义来更改方程中的字体.通过样式可以快速轻松地实现我们所需的公式格式,并统一所有公式的样式. 我们以如下公式来作为 ...

  5. LeetCode周赛#204 题解

    1566. 重复至少 K 次且长度为 M 的模式 #模拟 题目链接 题意 给定正整数数组 arr,请你找出一个长度为 m 且在数组中至少重复 k 次的模式. 模式 是由一个或多个值组成的子数组(连续的 ...

  6. Java基础教程——转换流

    转换流 通常,Window默认的编码方式是GBK,Java项目一般建议设为UTF-8编码.这时候读取文件可能出现乱码.事实上实际应用中编码格式不匹配的场景非常多. 转换流可以指定编码方式,用于解决乱码 ...

  7. 关于热力图的loss的一点感想

    网络的输出的热力图和gt相减的差矩阵,求其最大特征值的平方作为loss. 若图像h w不相等,可以使用奇异值代替特征值.奇异值往往对应着矩阵中隐含的重要信息,且重要性和奇异值大小正相关.每个矩阵A都可 ...

  8. Linux无法新增用户

    1.查看当前用户是否有权限创建用户 2.磁盘空间不足,vi打开/etc/passwd 报: E297: Write error in swap file"adduser.sh" 1 ...

  9. linux scp 命令使用

    1.scp命令使用 linux 把文件复制到另一台服务器上 复制文件 scp file_name user_name@remote_ip:file_path 复制文件夹 scp -r file_nam ...

  10. 老猿学5G:多量纲计费与QoS的QCI、5QI、ARP、GBR和MBR

    ☞ ░ 前往老猿Python博文目录 ░ 一.多量纲计费 多量纲计费是与传统的计费模式相区别的一种计费模式,传统的计费基本上都是通过使用量.使用时长或包固定时长等方式计费,而多量纲计费是指在考虑以上方 ...