ThreadLocal说明

类ThreadLocal主要为了解决每个线程绑定自己的私有的值,可以吧ThreadLocal比如可全部存放的数据,每个线程都可以在里面存放自己的数据,并且不会和其他线程冲突。

测试代码

package com.zhoutao.demo.thread;

import java.util.concurrent.TimeUnit;

public class ThreadLocalDemo {

  public static ThreadLocal<String> threadLocal = new ThreadLocal();

  public static void main(String[] args) {
// Initial value = null
System.out.println("Initial Value = " + threadLocal.get());
threadLocal.set("123");
ThreadA threadA = new ThreadA();
threadA.start();
// 得到是123
System.out.println("Main Get Value = " + threadLocal.get());
} static class ThreadA extends Thread { @Override
public void run() {
ThreadLocalDemo.threadLocal.set("ABC");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 得到的是ABC
System.out.println("Thread A Get Value = " + ThreadLocalDemo.threadLocal.get());
}
}
}

观察下面的代码可以验证上面的结论,Main线程保存的是123,那么在子线程A保存"ABC" 后,获取也是"123",这样我们就可以验证上面的结论了,那么我们看下get() 方法的JDK源码是如何实现的.

源码分析

可以看到,其首先或者当前的线程t,使用线程t获取到了当前LocalMap(这个类没有继承Map接口),那么说明这个map对象是和当前线程t相关的。如果该对象不存在,那么返会setInitialVale()方法.该方法也是通过线程t获取当前map,map为空则执行createMap方法完成创建。

    /**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
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();
} /**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
*
* @return the initial value
*/
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;
} protected T initialValue() {
return null;
}

修改初始化值

在SetInitialValue方法中,可以看到其调用了initialValue方法进行了初始化,在代码1中

    // Initial value = null
System.out.println("Initial Value = " + threadLocal.get());

可以看到没有设置初始值得情况下,其返回的是null,在上面的 protected T initialValue() 方法中也得到了验证,那么我们若要修改初始化值,仅要继承ThreadLocal类重写initialValue()方法即可,如下:

package com.zhoutao.demo.thread;

public class ThreadLocalExtend extends ThreadLocal<String> {

  @Override
protected String initialValue() {
return "DEFAULT INIT VALUE";
} public static void main(String[] args) {
ThreadLocalExtend extend = new ThreadLocalExtend();
System.out.println("初始化值为:" + extend.get());
}
}

从父线程继承数据

另外子线程也可以通过 InheritableThreadLocal 在子线程中获取从福线程继承下来的值。如上可以通过重写initialValue()方法修改初始化值,同时在可以获取父线程的数据的功能上,添加了通过childValue()方法修改从父线程获取的值,如:

package com.zhoutao.demo.thread;

public class InheritableThreadLocalExtend extends InheritableThreadLocal<String> {

  @Override
protected String initialValue() {
// 修改初始化值
return "default init value";
} @Override
protected String childValue(String parentValue) {
// 修改从父类获取的value
return parentValue.toUpperCase();
} public static void main(String[] args) {
InheritableThreadLocalExtend extend = new InheritableThreadLocalExtend();
System.out.println("初始化值为:" + extend.get());
}
}

ThreadLocal说明的更多相关文章

  1. ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...

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

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

  3. Threadlocal使用Case

    Threadlocal能够为每个线程分配一份单独的副本,使的线程与线程之间能够独立的访问各自副本.Threadlocal 内部维护一个Map,key为线程的名字,value为对应操作的副本. /** ...

  4. 多线程映射工具——ThreadLocal

    ThreadLocal相当于一个Map<Thread, T>,各线程使用自己的线程对象Thread.currentThread()作为键存取数据,但ThreadLocal实际上是一个包装了 ...

  5. ThreadLocal 工作原理、部分源码分析

    1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...

  6. ThreadLocal<T>的是否有设计问题

    一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...

  7. 理解ThreadLocal —— 一个map的key

    作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...

  8. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  9. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  10. ThreadLocal 源码剖析

    ThreadLocal是Java语言提供的用于支持线程局部变量的类.所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量(每个线程一个拷贝).在各个Java web的各种框架 ...

随机推荐

  1. Python中使用枚举类

    开发中我们经常定义常量, 其实有更好的方法:为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例.Python中提供了Enum类来实现这个功能: from enum im ...

  2. canvas实现随机验证码

    canvas实现随机验证码 知识点 canvas生成背景图和文字 设置字体样式和大小 String的fromCharCode(code码)生成大小写字母和数字 str.toLowerCase()转小写 ...

  3. vue 设计一个倒计时秒杀的组件

    简介: 倒计时秒杀组件在电商网站中层出不穷  不过思路万变不离其踪,我自己根据其他资料设计了一个vue版的 核心思路:1.时间不能是本地客户端的时间  必须是服务器的时间这里用一个settimeout ...

  4. HTML文档编写规范

    (1)HTML标记是由尖括号包围的关键词.所有标记均以“<”开始,以“>”结束.结束的标记在开始名称前加上斜杠“/”.例如头部标记格式如下所示:<head> ……</he ...

  5. HTML 练习js代码位置在head标签

    方式一: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  6. ArcGIS API for JavaScript 4.x 本地部署之IIS法

    [导读] 关于如何在默认网站(Default Web Site,物理地址C:\inetpub\wwwroot\)启动,已有很多博客详尽地写好了. 本篇在自建网站(本机)中配置http而非https的j ...

  7. 基于后端云的Android注册登录开发

    APP开发离不开注册登录功能,但是注册登录功能开发需要后台数据库的支持,对于一些初学者或者对后台数据 不熟悉的同学来说可能会有些困难.本文介绍一下后端云: 1. Bmob是国内起步较早的云后端服务平台 ...

  8. Javascript高级编程学习笔记(94)—— Canvas(11) 合成

    合成 除了之前介绍的属性之外,还有两个属性会应用到整个2d上下文中; globalAlpha 用于指定所有绘制的透明度 globalComposition 用于表示后绘制的图形怎样与先绘制的图形进行结 ...

  9. Java集合-ArrayList源码解析-JDK1.8

    ◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...

  10. linux(centos)上安装mysql教程,为需要远程登录的用户赋予权限

    最近把之前学生时代的win server换成了linux(centos)系统,因为win对于部署一些项目时候比较麻烦,直接入正题 1.准备阶段 我使用xshell工具管理服务器,相应下载和安装自行百度 ...