详述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( ...
随机推荐
- jQuery中$.fn
$.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效. 如扩展$.fn.abc(),即$.fn.abc()是对jquery扩展了一个abc方法,那么后面你的每一个 ...
- PHP加JS实现分片上传,断点续传
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title> ...
- 计算机二级-C语言-字符数字转化为整型数字。形参与实参类型相一致。double类型的使用。
//函数fun功能:将a和b所指的两个字符串分别转化成面值相同的整数,并进行相加作为函数值返回,规定只含有9个以下数字字符. //重难点:字符数字转化为整型数字. #include <stdio ...
- SVM的优缺点
优点 可用于线性/非线性分类,也可以用于回归,泛化错误率低,也就是说具有良好的学习能力,且学到的结果具有很好的推广性. 可以解决小样本情况下的机器学习问题,可以解决高维问题,可以避免神经网络结构选择和 ...
- 在Linux系统中使用ntfs、fat32格式的存储设备
在Linux系统中使用ntfs.fat32格式的存储设备 我们通常使用的移动硬盘或U盘一般都是ntfs或fat32的文件系统,作为一名运维工程师,经常会遇到把移动硬盘或者U盘上的内容拷贝的Linu ...
- JS线程及回调函数执行
JS是单线程的程序,在某些方面来讲并不是十分准确.在浏览器的内核里面有很多的模块,比如js的解释执行的模块,html.css的处理模块,渲染模块等,多数模块是单线程执行的,但是有几个模块是多线程的,比 ...
- intellij idea设置(字体大小、背景)
1. 配置信息说明 Intellij Idea: 2017.2.5 2.具体设置 <1> 设置主题背景.字体大小 File---->Settings----->Appearan ...
- pwn之exp问题反馈和ASLR认知
如上问题是我执行脚本遇到的,改了脚本几次,依然没变,嗯...... 当我用了百度,据说是ALSR没关,的确,这导致我脚本中的addr是一个随机数,从而攻击失败 ##0x00:引用一下查到的知识:在传统 ...
- 转载和补充:Oracle中的一些特殊字符
oracle通配符,运算符的使用 用于where比较条件的有: 等于:=.<.<=.>.>=.<> 包含:in.not in exists.not exists 范 ...
- 「JSOI2010」旅行
「JSOI2010」旅行 传送门 比较妙的一道 \(\text{DP}\) 题,思维瓶颈应该就是如何确定状态. 首先将边按边权排序. 如果我们用 \(01\) 串来表示 \(m\) 条边是否在路径上, ...