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代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
随机推荐
- MP实战系列(二)之集成swagger
其实与spring+springmvc+mybatis集成swagger没什么区别,只是之前写的太不好了,所以这次决定详细写. 提到swagger不得不提rest,rest是一种架构风格,里面有对不同 ...
- jmeter(十八)关联之XPath Extractor
之前的博客,有介绍jmeter如何对请求进行关联的一种常见用法,即:后置处理器中的正则表达式提取器,下面介绍另一种关联方法,XPath Extractor! 所谓关联,从业务角度讲,即:某些操作步骤与 ...
- 学习CSS布局 - box-sizing
box-sizing 人们慢慢的意识到传统的盒子模型不直接,所以他们新增了一个叫做 box-sizing 的CSS属性. 当你设置一个元素为 box-sizing: border-box; 时,此元素 ...
- Java中没有引用传递只有值传递(在函数中)
◆传参的问题 引用类型(在函数调用中)的传参问题,是一个相当扯的问题.有些书上说是传值,有些书上说是传引用.搞得Java程序员都快成神经分裂了.所以,我们最后来谈一下“引用类型参数传递”的问题. 如下 ...
- python init 方法 与 sql语句当前时间对比
def init(self,cr): tools.sql.drop_view_if_exists(cr, 'custrom_product_infomation_report') cr.execute ...
- 安全提示:IIS不要开启“WebDAV”扩展(转载)
在IIS设置里,有一个“Web服务扩展”的设置,其中包括“WebDAV”扩展.许多人都不明白,这个“WebDAV”扩展是干嘛用的,要不要开启呢?有不少人的想法是“开启吧,以免影响网站运行,启用总比不启 ...
- chrome浏览器直接打印 - z
在地址栏敲: about:flags ,打开设置界面:停用:Enable Print Preview Registration PromosChrome快捷方式增加:--kiosk-printing这 ...
- c# create html table test
string html = "<html><head><title>44444444</title>"; html += @&quo ...
- C# webApi上传图片 代码篇
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 代码篇,不多说 如下: using System; using System.Collections.Generic; using System.D ...
- NOI Day1线上同步赛梦游记
Preface 第一次体验NOI,虽然不是正式选手,但是打打同步赛还是挺涨姿势的,也算是体验了一把. Day1很爆炸,一方面是NOI题目的难度高于自身的水平,另一方面也出现了比较大的失误,T1一个数组 ...