详述ThreadLocal
ThreadLocal的作用和目的:用于实现线程内的数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据。
举一个反面例子,当我们使用简单的int类型存储线程间共享的数据,但在另外一个线程我们想共享另外一份数据,此时就会造成数据混淆的现象,如下:
package com.zzj.test;
import java.util.Random;
public class Test {
private static int data;
public static void main(String[] args) {
for(int i = 1; i <= 2; i ++) {
new Thread(() -> {
data = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " has get data: " + data);
new A().get();
new B().get();
}).start();
}
}
private static class A{
public void get() {
System.out.println("A from " + Thread.currentThread().getName() + " has get data: " + data);
}
}
private static class B{
public void get() {
System.out.println("B from " + Thread.currentThread().getName() + " has get data: " + data);
}
}
}
运行结果如下:

而当我们使用ThreadLocal时,就不会出现数据混淆的现象:
public class Test {
private static ThreadLocal<Integer> tl = new ThreadLocal<>();
public static void main(String[] args) {
for(int i = 1; i <= 2; i ++) {
new Thread(() -> {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " has get data: " + data);
tl.set(data);
new A().get();
new B().get();
}).start();
}
}
private static class A{
public void get() {
int data = tl.get();
System.out.println("A from " + Thread.currentThread().getName() + " has get data: " + data);
}
}
private static class B{
public void get() {
int data = tl.get();
System.out.println("B from " + Thread.currentThread().getName() + " has get data: " + data);
}
}
}
结果如下:

我们找到ThreadLocal的源码,看看其基本运行原理:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
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();
}
// 通过静态内部类实现变量与线程绑定
static class ThreadLocalMap {...}
ThreadLocal基本运行过程:每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key是各自的线程对象,value是各自的set方法传进去的值。在线程结束时可以调用ThreadLocal.clear()方法,这样会更快地释放内存,不调用在线程结束后也会自动释放相关的ThreadLocal变量。
结论--我们结合源码和上述两个例子可以看出:
详述ThreadLocal的更多相关文章
- ThreadLocal使用和原理简析
1. 解决共享资源冲突 对于并发工作,需要某种方式来防止两个任务同时访问相同的资源,至少在关键阶段不能出现这种冲突情况. 方法之一就是当资源被一个任务使用时,在其上加锁.第一个访问某项资源的任务必须锁 ...
- Android10_原理机制系列_Android消息机制(Handler)详述
概述 在Android中的多进程.多线程中提过,只有主线程(UI线程)可以更新UI,其他线程不可以,所以一般耗时操作放到子线程.子线程可以通过Handler将相关信息通知到主线程. Android的消 ...
- ThreadLocal简单理解
在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- Threadlocal使用Case
Threadlocal能够为每个线程分配一份单独的副本,使的线程与线程之间能够独立的访问各自副本.Threadlocal 内部维护一个Map,key为线程的名字,value为对应操作的副本. /** ...
- 多线程映射工具——ThreadLocal
ThreadLocal相当于一个Map<Thread, T>,各线程使用自己的线程对象Thread.currentThread()作为键存取数据,但ThreadLocal实际上是一个包装了 ...
- ThreadLocal 工作原理、部分源码分析
1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...
- ThreadLocal<T>的是否有设计问题
一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...
- 理解ThreadLocal —— 一个map的key
作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...
随机推荐
- Go语言基础之runtime包
文章引用自 Golang中runtime的使用 runtime调度器是非常有用的东西,关于runtime包几个方法: Gosched:让当前线程让出cpu以让其他线程运行,它不会挂起当前线程,因此当前 ...
- JS知识点查漏补缺
知识点1: 判断语句中遇到NaN即为 False 只需要注意遇到False即为False即可 使用join(),toString()皆可以将数组转化为字符串 二者的相同点在于都可以转化数组为字符串 二 ...
- WCF全面解析之三 使用配置文件启动WCF服务
知识:WCF地址.WCF绑定 Endpoint的配置 服务的三要素(ABC) A:Address 地址 有传输方式信息 B:Binding 怎么做(与地址的传输方式要匹配) C:Contract 做什 ...
- CAS 和 ABA 问题
CAS简介 CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制. CAS 它是一条CPU并发原语.操作包含三个操作数 -- 内存位置.预期数值和新值.CAS ...
- Vue项目引进ElementUI组件
1.https://blog.csdn.net/Mr_JavaScript/article/details/80741914 1.1 安装 npm install element-ui -save 1 ...
- JS vue 组件创建过程
https://www.jianshu.com/p/3504a1edba42 vue.js原生组件化开发(一)——组件开发基础 0.3472017.05.09 12:00:54字数 1120阅读 33 ...
- Android读取权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <use ...
- Dart语言学习(十四) Dart泛型
什么是泛型? 通俗理解:泛型就是解决 类 接口 方法的复用性.以及对不特定数据类型的支持(类型校验) 如下代码,只能返回string类型的数据 String getData(String value) ...
- GO测试
测试 Go拥有一个轻量级的测试框架,它由 go test 命令和 testing 包构成. 你可以通过创建一个名字以 _test.go 结尾的,包含名为 TestXXX 且签名为 func (t *t ...
- Caffe2 手册(Intro Tutorial)[2]
Caffe2的相关概念 接下来你可以学到更多Caffe2中主要的概念,这些概念对理解和开发Caffe2相当重要. Blobs and Workspace,Tensors Caffe2中,数据是 ...