一、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. FL Studio杂项设置页讲解(下)

    上篇文章中我们重点讲解了FL Studio中"截断/被截"如何有效的避免个采样在播放时相互干扰的知识以及电平设置栏的知识,今天我们将讲完该页面中剩下的栏目知识,一起来看看吧! 1. ...

  2. FL Studio乐理教程之调式音阶

    在我们使用FL制作音乐时,乐理是必不可少的制作基础,本篇教程将结合FL Studio为大家讲解基础乐理及在FL Studio20中的使用技巧. 添加一个乐器,打开Piano Roll(钢琴窗). 首先 ...

  3. Dynamics 365-表单元素取值/赋值

    取值/赋值 参考: 山人丶 提示: 查找类型赋值时需指定目标实体,记录名称及id值 时间和日期类型赋值时需赋值Date类型 //获取new_name的值(单行文本) Xrm.Page.getAttri ...

  4. yii2.0 设置默认路由

    在config/web.php 添加 $config = [ 'defaultRoute' => 'login/login', ];

  5. 与运算(&)、或运算(|)、异或运算(^)、右移运算符(>>>)本质介绍

    按位与运算符(&) 参加运算的两个数据,按二进制位进行"与"运算. 运算规则:0&0=0;  0&1=0;   1&0=0;    1&1= ...

  6. Java集合【3】-- iterable接口超级详细解析

    目录 iterable接口 1. 内部定义的方法 1.1 iterator()方法 1.2 forEach()方法 1.3 spliterator()方法 总结 iterable接口 整个接口框架关系 ...

  7. sentinel整合dubbo

    <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-dubbo-a ...

  8. 冲刺随笔——Day_Four

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 ...

  9. Django 多对多表的三种创建方式

    第一种: class Book(models.Model): name = models.CharField(max_length=32) # 第一种自动创建 authors = models.Man ...

  10. 小样本元学习综述:A Concise Review of Recent Few-shot Meta-learning Methods

    原文链接 小样本学习与智能前沿 . 在这个公众号后台回复'CRR-FMM',即可获得电子资源. 1 Introduction In this short communication, we prese ...