详述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语言基础之os
文章引用自 package os import "os" os包提供了操作系统函数的不依赖平台的接口.设计为Unix风格的,虽然错误处理是go风格的:失败的调用会返回错误值而非错误 ...
- 用svn客户端checkout时报错RA layer request failed
用svn客户端checkout时报错: RA layer request failedsvn: Unable to connect to a repository at URL 'https://30 ...
- Plastic Bottle Manufacturer - Different Cosmetic Plastic Bottle Materials, Different Characteristics
Plastic bottles are usually made of PP, PE, K, AS, abs, acrylic, PET, and the like. Dust caps for th ...
- numpy常用函数之arange函数
2.np.arange([start, ]stop, [step, ]dtype=None) 作用: arange函数用于创建等差数组 start:可忽略不写,默认从0开始;起始值 stop:结束 ...
- HDU 1035 Robot Motion(dfs + 模拟)
嗯... 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1035 这道题比较简单,但自己一直被卡,原因就是在读入mp这张字符图的时候用了scanf被卡. ...
- sql语句插入时提示:“Duplicate entry 'XXX' for key 1 ” 是什么原因?
你用的是MYSQL 数据库吧? 1:提示信息翻译:插入 xxx 使索引1重复分析:索引如果是primary unique这两两种,那么数据表的数据对应的这个字段就必须保证其每条记录的唯一性.否则就会产 ...
- 解决CentOS下boost安装后不能使用的问题
先说一说整个经历. 因为之前没有注意到gcc4.8.5比较旧,就已经安装好boost了,当时已经可以使用了,后来发现gcc太老了,一些软件安装需要比较新的gcc支持,所以决定升级gcc,结果boost ...
- springboot默认创建的bean是单实例
默认是单例 通过注解@Scope("prototype"),将其设置为多例模式 参考: 曾经面试的时候有面试官问我spring的controller是单例还是多例,结果我傻逼的回答 ...
- springboot搭建的web数据提交乱码
修改:application.yml或者application.properties文件 将 url: jdbc:mysql://127.0.0.1:3306/shiro 修改为: url: jdbc ...
- 笔记-python-lib—data types-enum
笔记-python-lib—data types-enum 1. enum Source code: Lib/enum.py 文档:https://docs.python.org/3/lib ...