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. Caffe源码理解1:Blob存储结构与设计

    博客:blog.shinelee.me | 博客园 | CSDN Blob作用 据Caffe官方描述: A Blob is a wrapper over the actual data being p ...

  2. token:NLP之词形还原

    已迁移到我新博客,阅读体验更佳token:NLP之词形还原 完整代码实现放在我的github上:click me 一.任务描述 形态还原算法: 输入一个单词 如果词典里有该词,输出该词及其属性,转4, ...

  3. Quartz.Net学习笔记

    一.概述 Quartz.NET是一个强大.开源.轻量的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改写,可用于winform和asp.net应用中.它灵 ...

  4. ACM入门之OJ~

    所谓OJ,顾名思义Online Judge,一个用户提交的程序在Online Judge系统下执行时将受到比较严格的限制,包括运行时间限制,内存使用限制和安全限制等.用户程序执行的结果将被Online ...

  5. 怎么让DIV在另一个DIV里靠底部显示?

    可以使用css的position属性的绝对定位. 拓展知识 position 属性指定了元素的定位类型. position 属性的五个值: static:HTML元素的默认值,即没有定位,元素出现在正 ...

  6. css公共库——简介中超过长度显示省略号

    在简介.引言中常见:文字只有一排,超出宽度以省略号显示,像这样 实现方法:在公共库定义otw类 .otw{ overflow: hidden; text-overflow: ellipsis; whi ...

  7. oracle如何查看当前有哪些用户连接到数据库

    可以执行以下语句:select username,serial#, sid from v$session; ---查询用户会话alter system kill session 'serial#, s ...

  8. scrapy爬虫 快速入门

    Scrapy 1. 简介 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络 ...

  9. webpack4打包nodejs项目进阶版——多页应用模板

    前段时间我写了个打包nodejs项目的文章,点击前往 但是,问题很多.因为之前的项目是个历史遗留项目,重构起来可能会爆炸,当时又比较急所以就写个的适用范围很小的webpack的打包方法. 最近稍微得空 ...

  10. Spring Boot 集成 Swagger,生成接口文档就这么简单!

    之前的文章介绍了<推荐一款接口 API 设计神器!>,今天栈长给大家介绍下如何与优秀的 Spring Boot 框架进行集成,简直不能太简单. 你所需具备的基础 告诉你,Spring Bo ...