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 理解的更多相关文章

  1. java ThreadLocal理解和使用

    一.ThreadLoal的理解 ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String ...

  2. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  3. Java ThreadLocal 源代码分析

    Java ThreadLocal 之前在写SSM项目的时候使用过一个叫PageHelper的插件 可以自动完成分页而不用手动写SQL limit 用起来大概是这样的 最开始的时候觉得很困惑,因为直接使 ...

  4. [java] 深入理解内部类: inner-classes

    [java] 深入理解内部类: inner-classes // */ // ]]>   [java] 深入理解内部类: inner-classes Table of Contents 1 简介 ...

  5. Java初始化理解与总结 转载

    Java的初始化可以分为两个部分: (a)类的初始化 (b)对象的创建 一.类的初始化 1.1 概念介绍: 一个类(class)要被使用必须经过装载,连接,初始化这样的过程. 在装载阶段,类装载器会把 ...

  6. 从Java视角理解CPU上下文切换(Context Switch)

    从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态   在高性能编程时,经常接触到多线程. 起初我们的理解是, 多个线程并行地执行总比单个线程要快, 就像多个人一起干活总比一个人干要快 ...

  7. 从Java视角理解CPU缓存(CPU Cache)

    从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多 ...

  8. Java IO 理解流的概念

    Java IO 理解流的概念 @author ixenos 在理解流时首先理解以下概念 1.流的来源和去向一般在构造器指出 2.方法中的形参一般是将流输出到某个位置,读取(INPUT)流从流读出数据( ...

  9. Effective Java通俗理解(持续更新)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

随机推荐

  1. wordpress之插件安装和主题安装(包含常见问题)

    问题描述:安装WordPress主题及插件需要输入FTP问题,要执行请求的操作,WordPress需要访问您网页服务器的权限.请输入您的FTP登陆凭据以继续 执行如下两条命令即可安装成功: sudo ...

  2. [转]QGis2.9在windows下的编译以及二次开发包下载

    今天心血来潮,将QGis在github上的代码更新后,又编译了一下.留意到源代码包里面的INSTALL文件有更新,于是本次编译完全基于官方的编译说明.编译过程非常顺利,除了在CMake的第一次conf ...

  3. POJ2253(dijkstra堆优化)

    https://vjudge.net/problem/POJ-2253 Freddy Frog is sitting on a stone in the middle of a lake. Sudde ...

  4. css3渐变特性

    项目中,一般用于业务办理的进度条,设置背景色,纯背景色可以直接设置,如果是渐变色,那使用line-gradient渐变特性就需要设置渐变的位置了入下图 方法一.直接在进度条轨道上面再加一个元素,用于设 ...

  5. AIS系统(转)

    船舶自动识别系统(Automatic Identification System, 简称AIS系统)由岸基(基站)设施和船载设备共同组成,是一种新型的集网络技术.现代通讯技术.计算机技术.电子信息显示 ...

  6. ESP8266 wifi钓鱼

    原文链接: https://www.cnblogs.com/xiaowuyi/p/6980072.html https://www.cnblogs.com/xiaowuyi/p/7110652.htm ...

  7. grep配置颜色显示

    查日志时候必须要用的命令,为了在终端方便显示查看,可以加颜色和高亮等设置. 自己习惯用的: GREP_COLOR='a;b'  a=4表示下划线,b=41表示红色背景高亮 在~/.bashrc文件中加 ...

  8. VS诊断工具打开失败

    使用管理员模式打开cmd,输入以下命令~ C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -iC:\Windows\Micros ...

  9. java算法----排序----(6)希尔排序(最小增量排序)

    package log; public class Test4 { /** * java算法---希尔排序(最小增量排序) * * @param args */ public static void ...

  10. NOIP2002-2017普及组题解

    虽然普及组一般都是暴力省一,但是有一些题目还是挺难的qwq个人觉得能进TG的题目会在前面打上'*' NOIP2002(clear) #include<bits/stdc++.h> usin ...