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. Pycharm:书签的使用

    创建匿名书签 有时候我们的代码会写很长,为了查找方便,我们会在经常需要查看的地方插入一个书签.在 Pycharm 中,将光标移动到需要创建书签的行,按 F11 可以创建一个匿名书签,匿名书签的显示是行 ...

  2. Java开发环境Jave EE 和 jdk 下载

    以下软件均为64位环境 jdk版本:jdk1.8.0_181 jave EE版本(当前最新版本4.8):eclipse-jee-photon-R-win32-x86_64.zip 链接:https:/ ...

  3. 解决ruby安装后无法添加淘宝gem源------------学习记录

    使用sass ,需要安装ruby,会建议移除gem源,添加淘宝的gem源,但是淘宝的镜像源已经停止维护啦!!用https://gems.ruby-china.com 代替即可. 操作如下: 1)删除原 ...

  4. REST API disable / enable service auto start by API

    how to disable service auto start by API as the following how to enable service auto start by API as ...

  5. How to resolve CSRF protection error while adding service through Ambari api

    Short Description: This article will describe on how to disable CSRF protection in Ambari. Article A ...

  6. 总结Java常用到的六个加密技术和代码

    加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容.大体上分为双向加密和单向加密,而双向加密又分为对称加密和非对称加密(有些 ...

  7. 说一下Dubbo 的工作原理?注册中心挂了可以继续通信吗?

    面试题 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程? 面试官心理分析 MQ.ES.Redis.Dubbo,上来先问你一些思考性的问题.原理,比如 kaf ...

  8. PHP全栈学习笔记17

    phpmyadmin教程 管理页进入phpmyadmin 打开C:\wamp\apps\phpmyadmin3.5.1下的配置文件:config.inc 修改密码 创建与修改数据库.数据表 字段类型 ...

  9. Python学习之路——Day01

    Day01 一.编程和编程语言 编程语言是人与计算机之间交流沟通的介质 编程就是人实现通过让计算机实现动作的文件 二.计算机的组成 1.控制器:负责控制指挥计算机硬件运行 2.运算器:负责数学与逻辑运 ...

  10. .NET Core TDD 前传: 编写易于测试的代码 -- 缝

    有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户就不敢 ...