Java ThreadLocal 理解
ThreadLocal 概念:
ThreadLocal不是用来解决对象共享访问的问题,而主要是提供了保存对象的方法和避免参数传递的方便的对象访问方式。
ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量的时候ThreadLocal为每一个使用该变量的线程提供了独立的变量副本,也就是说每一个线程都可以单独改变自己的副本,而不会影响其他线程的副本。
从线程的角度来看目标变量就是当前线程的本地变量,这也就是类名Local的含义。
ThreadLocal的4个方法:
void set(T value) 将此线程局部变量的当前线程副本中的值设置为指定值
void remove() 移除此线程局部变量当前线程的值
protected T initialValue() 返回此线程局部变量的当前线程的初始值
T get() 返回此线程局部变量的当前线程副本中的值
注意 :默认情况下 initValue(), 返回 null 。线程在没有调用 set 之前,第一次调用 get 的时候, get方法会默认去调用 initValue 这个方法。所以如果没有覆写这个方法,可能导致 get 返回的是 null 。当然如果调用过 set 就不会有这种情况了。但是往往在多线程情况下我们不能保证每个线程的在调用 get 之前都调用了set ,所以最好对 initValue 进行覆写,以免导致空指针异常。
ThreadLocal实现原理:
ThreadLocal是如何做到为每一个线程维护变量的副本呢?让我们来看看ThreadLocal的源码:
public class ThreadLocal<T> {
public T get() {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程的threadLocals变量
ThreadLocalMap map = getMap(t);
// 从当前线程的threadLocals变量中取得本threadLocal为key的值
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T) e.value;
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
public void set(T value) {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程的threadLocals变量
ThreadLocalMap map = getMap(t);
// 以本threadLocal为key的保存值到当前线程的threadLocals变量中去
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
在ThreadLocal类中有一个map,用于存储没一个线程的变量副本,map中的元素key为线程对象 value为线程副本中的变量值
示例:
package cn.com.example; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* Created by Jack on 2017/2/13.
*/
public class ThreadLocalTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 3; i++) {
executorService.execute(new ThreadTest());
} executorService.shutdownNow();
}
} class ThreadTest implements Runnable { @Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " value=" + ThreadLocalNumber.get());
}
}
} class ThreadLocalNumber {
private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() {
protected synchronized Integer initialValue() {
return 0;
}
}; public static void set() {
value.set(value.get() + 1);
} public static int get() {
// 为了测试 直接在get里面 ++
value.set(value.get() + 1);
return value.get();
}
}
结果:
pool-1-thread-3 value=1
pool-1-thread-2 value=1
pool-1-thread-1 value=1
pool-1-thread-2 value=2
pool-1-thread-3 value=2
pool-1-thread-2 value=3
pool-1-thread-1 value=2
pool-1-thread-2 value=4
pool-1-thread-2 value=5
pool-1-thread-3 value=3
pool-1-thread-3 value=4
pool-1-thread-3 value=5
pool-1-thread-1 value=3
pool-1-thread-1 value=4
pool-1-thread-1 value=5
从运行结果得知 各线程都用于各自的Local变量,并各自读写互不干扰。
Java ThreadLocal 理解的更多相关文章
- java ThreadLocal理解和使用
一.ThreadLoal的理解 ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- Java ThreadLocal 源代码分析
Java ThreadLocal 之前在写SSM项目的时候使用过一个叫PageHelper的插件 可以自动完成分页而不用手动写SQL limit 用起来大概是这样的 最开始的时候觉得很困惑,因为直接使 ...
- [java] 深入理解内部类: inner-classes
[java] 深入理解内部类: inner-classes // */ // ]]> [java] 深入理解内部类: inner-classes Table of Contents 1 简介 ...
- Java初始化理解与总结 转载
Java的初始化可以分为两个部分: (a)类的初始化 (b)对象的创建 一.类的初始化 1.1 概念介绍: 一个类(class)要被使用必须经过装载,连接,初始化这样的过程. 在装载阶段,类装载器会把 ...
- 从Java视角理解CPU上下文切换(Context Switch)
从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态 在高性能编程时,经常接触到多线程. 起初我们的理解是, 多个线程并行地执行总比单个线程要快, 就像多个人一起干活总比一个人干要快 ...
- 从Java视角理解CPU缓存(CPU Cache)
从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多 ...
- Java IO 理解流的概念
Java IO 理解流的概念 @author ixenos 在理解流时首先理解以下概念 1.流的来源和去向一般在构造器指出 2.方法中的形参一般是将流输出到某个位置,读取(INPUT)流从流读出数据( ...
- Effective Java通俗理解(持续更新)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
随机推荐
- SpringBoot实战(十四)之整合KafKa
本人今天上午参考了不少博文,发现不少博文不是特别好,不是因为依赖冲突问题就是因为版本问题. 于是我结合相关的博文和案例,自己改写了下并参考了下,于是就有了这篇文章.希望能够给大家帮助,少走一些弯路. ...
- mybatis逆向工程之动态web项目
有了逆向工程,单表的增删改查以及相关的实体类,还有属性注释都不用自己写了,都可以自动化生成,只需如下三步即可 逆向工程的优点是:自动化生成实体类和对应的增删改查,效率相对于之前个人开发时一个个写增删改 ...
- 阅读Cortex-A53 Technical Reference Manual笔记
1. 前言 一颗芯片最主要的就是CPU核了,处理CPU Core之外,还存在很多其他IP,包括Graphical.Multimedia.Memory Controller.USB Controller ...
- ORA-10858:在要求输入数字处找到非数字字符
今天在写sql语句的时候,运行报错:ORA-10858:在要求输入数字处找到非数字字符 在网上查了一下为什么会有这种错误,有一个建议是可能是写的sql语句中的日期没有处理.仔细看了一下自己写的代码 就 ...
- Struts学习总结-02 上传文件
Struts 2框架提供了内置支持处理文件上传使用基于HTML表单的文件上传.上传一个文件时,它通常会被存储在一个临时目录中,他们应该由Action类进行处理或移动到一个永久的目录,以确保数据不丢失. ...
- [Oracle]为何Archivelog 没有马上被删除
[Oracle]为何Archivelog 没有马上被删除 客户设置了 Archivelog 的 deletion policy 是 CONFIGURE ARCHIVELOG DELETION POLI ...
- Tensorflow实例:利用LSTM预测股票每日最高价(一)
RNN与LSTM 这一部分主要涉及循环神经网络的理论,讲的可能会比较简略. 什么是RNN RNN全称循环神经网络(Recurrent Neural Networks),是用来处理序列数据的.在传统的神 ...
- .NetCore实践篇:成功解决分布式监控ZipKin聚合依赖问题(三)
前言 读本篇文章之前,可以先读前两篇文章.为了照顾没看过的朋友,我也会稍作复习. 思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统? 实践篇一:.NetCore实践篇:分布式监控客户端 ...
- JVM规范系列第2章:Java虚拟机结构
本规范描述的是一种抽象化的虚拟机的行为,而不是任何一种(译者注:包括 Oracle 公司自己的 HotSpot 和 JRockit 虚拟机)被广泛使用的虚拟机实现. 记住:JVM规范是一种高度抽象行为 ...
- Linux下环境变量配置方法梳理(.bash_profile和.bashrc的区别)
在linux系统下,如果下载并安装了应用程序,在启动时很有可能在键入它的名称时出现"command not found"的提示内容.如果每次都到安装目标文件夹内,找到可执行文件来进 ...