一、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. 通过Folx的排序功能来设置下载任务的优先级

    当我们使用Folx进行多任务下载时,突然遇到要下载一个紧急文件的情况,该如何让这个紧急文件的下载任务排在优先的位置?当然,用户也可以先暂停所有的下载任务,仅开启紧急文件的下载任务. 但这种方式需要用户 ...

  2. MindManager中主题间距/线条粗细的灵活调整

    在MindManager中,主题和线条是思维导图的基本元素,只有通过它们才能将要表达的思想呈现.并联系起来.因此,关于它们的属性设置就会多一点,如颜色.宽度.位置等.而调整主题之间的距离及线条的粗细, ...

  3. jQuery 第五章 实例方法 详解内置队列queue() dequeue() 方法

    .queue() .dequeue() .clearQueue() ------------------------------------------------------------------ ...

  4. 解决Jenkins可安装界面是空白的小技巧

    打开后这里面最底下有个[升级站点],把其中的链接改成http的就好了,http://updates.jenkins.io/update-center.json. 然后在服务列表中关闭jenkins,再 ...

  5. AA:白细胞计数

    总时间限制:  1000ms 内存限制:  65536kB 描述 医院采样了某临床病例治疗期间的白细胞数量样本n份,用于分析某种新抗生素对该病例的治疗效果.为了降低分析误差,要先从这n份样本中去除一个 ...

  6. mq消息消费,broker选址

    PullRequest.MessageQueue.BrokerName 根据PullRequest.MessageQueue得到brokerId,默认0或者用缓存中的suggest,每次消息拉取后会更 ...

  7. 学会了这一招,距离Git大神不远了!

    大家好,今天我们来介绍git当中一项非常重要的功能--交互式工具 有的时候如果我们要处理的文件很多,使用git add .等操作会非常有隐患,因为很有可能我们一不小心就疏忽了一些内容.如果我们使用一个 ...

  8. Golang性能分析与优化

    在公司的分享,去除了相关的敏感信息.

  9. C中memcpy函数用法

    1.函数原型 void *memcpy(void *destin,void *source,unsigned n); 其中, destin代表用于存储复制内容的目标数组,类型强制转换为void*指针. ...

  10. 硬RAID和软RAID

    RAID简介: RAID是 Redundant Array of Independent Disks的简写,意为独立磁盘冗余阵列,简称磁盘阵列.基本思想是把多个相对便宜的硬盘结合起来,称为一个磁盘阵列 ...