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. Java3y文章目录导航

    由于写的文章已经是有点多了,为了自己和大家的检索方便,于是我就做了这么一个博客导航. 想要获取最新原创的技术文章欢迎关注我的公众号:Java3y 文章目录导航:https://github.com/Z ...

  2. gitbook 入门教程之前置知识

    markdown 基本知识 markdown 是一种简化的 html 语法,相比于 txt 无格式文本更强大. 你可以用专门的软件去编辑 markdown 文件,就像需要使用软件编辑 txt 文件一样 ...

  3. (办公)springboot配置aop处理请求.

    最近项目用到springboot,就是需要配置一些东西.比如用aop处理请求.方法前通知获取url,method,ip,类方法,参数,方法后通知,返回参数,而且还可以记录一下日志.下面是操作的代码. ...

  4. Linux下使用ntpdate进行时间同步

    转摘自Linux下使用ntpdate进行时间同步https://www.cnblogs.com/zhi-leaf/p/6281549.html1.安装ntpdate,执行以下命令 # yum inst ...

  5. WinForm DataGridView双向数据绑定

    程序目标: 实现DataGridView与BindingList<T>双向绑定.用户通过DataGridView修改值后立即更新BindList对象的值,代码修改BindList后立即更新 ...

  6. lombok的安装

    Lombok简介 Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法.官方地址:https:/ ...

  7. 白话kubernetes的十万个为什么(持续更新中...) - kubernetes

    Kubernetes简称? 答:k8s或kube. Kubernetes是什么? 答:由Google开发的一个强大的平台,可以在集群环境中管理容器化应用程序.本质上是一种特殊的数据库,里面存储的是能够 ...

  8. spring集成shiro登陆流程(上)

    上一篇已经分析了shiro的入口filter是SpringShiroFilter, 那么它的doFilter在哪儿呢? 我们看到它的直接父类AbstractShrioFilter继承了OncePerR ...

  9. 查看网卡及对应的IP、MAC

    #!/bin/bash# judge OS OS_release=`cat /etc/redhat-release | awk '{print $(NF-1)}'|cut -c 1`# To obta ...

  10. java中的int与byte的转化

    java中的int与byte的转化 1.基础准备 1.1.原码 就是二进制码,最高位为符号位,0表示正数,1表示负数,剩余部分表示真值 1.2.反码 在原码的基础上,正数反码就是他本身,负数除符号位之 ...