你有时候想要通过每个线程的数据(如一个用户的ID)连接一个线程。尽管你可以使用局部变量完成这个任务,仅仅只有局部变量存在时你才可以这样做。你可以用一个实例的字段去长久保存这个数据,但是你需要去处理同步。幸好,Java提供了java.lang.ThreadLocal类作为一个简的替换使用。
    每个ThreadLocal实例是一个线程局部变量(Thread-Local Variables),这个局部变量为每个访问变量的线程提供单独的存储槽。你可以认为一个线程局部变量是一个多槽的变量,在它的每个线程里可以存储相同变量的不同值。每个线程只关注自己的值,和不关注其它线程它们自己的值在这变量中。
     ThreadLocal的声明是ThreadLocal<T>,这个T是指示值的类型用于存储在这个变量中。这个类声明了如下的构造器和方法:
        (1)ThreadLocal:创建一个新的线程局部变量。
        (2) T get():在请求线程存储槽中返回值。当线程请求这个方法,而线程存储槽不存在,那么get()会去请求initialValue()方法。
        (3)T initialValue():创建请求线程存储槽,和存储默认值在这个存储槽。这个初始值是null。你必须创建ThreadLocal的子类,并重写它的protected方法去提供更多有效的值。
        (4)void remove():移除请求线程存储槽。如果这个方法调用get()却没使用set()。那么这个get()会调用initialValue()方法。
            void set(T value):将值放入到请求线程存储槽。

Listing4-3展示了如何使用ThreadLocal去连接两个线程的不同用户IDs

package com.owen.thread.chapter4;public class ThreadLocalDemo
{private static volatile ThreadLocal<String> userID = new ThreadLocal<String>();public static void main(String[] args){Runnable r = new Runnable(){@Overridepublic void run(){String name = Thread.currentThread().getName();if (name.equals("A"))userID.set("foxtrot");elseuserID.set("charlie");System.out.println(name + " " + userID.get());}};Thread thdA = new Thread(r);thdA.setName("A");Thread thdB = new Thread(r);thdB.setName("B");thdA.start();thdB.start();}
}

之后实例化ThreadLocal和定义一个引用volatile的全局类命名为userID(这个全局是一个volatile因为它需要通过不同的线程,它可能在多处理器或多核机器上运行——用它代替final),默认主线程创建两个或多线程,它存储不同的java.lang.String.object在userID中,和输出它们的对象。
   执行上面的代码,你将会看到:

A foxtrot
B charlie

值存储在线程局部变量中,而这些值之间没有联系。当一个新的线程被创建,它获取一个新的存储槽包含initialValue()的值。可能你需要涉及来自一个父线程(a parent thread)的值,一个线程创建另一个线程,给一个子线程,这个线程是创建过的。你可以用InheritableThreadLocal来完成任务。
  InheritableThreadLocal是ThreadLocal的一个子类。下面也就是我们所知道的InheritableThreadLocal的构造器:
      (1)T childValue(T parentValue):计算子类的初始值作为一个父值的应用,这个时候子线程被创建。在子线程被创建之前这个方法从父线程中请求。这个方法从parentValue中返回参数,和当其它值被要求时这个方法需要重写。
     Listing4-4展示如何运用InheritableThreadLocal通过父线程的Integer对象给子线程。
      Listing4-4通过父线程的对象给一个子线程。

package com.owen.thread.chapter4;public class InheritableThreadLocalDemo
{private static final InheritableThreadLocal<Integer> intVal = new InheritableThreadLocal<Integer>();public static void main(String[] args){Runnable rP = () -> {intVal.set(new Integer(10));Runnable rC = () -> {Thread thd = Thread.currentThread();String name = thd.getName();System.out.printf("%s %d%n", name, intVal.get());};Thread thdChild = new Thread(rC);thdChild.setName("Child");thdChild.start();};new Thread(rP).start();}}

之后初始化InheritableThreadLocal和定义它为final类的变量(也可以用volatile替代)命名为intVal,这个默认线程创建一个父线程,它存储一个java.lang.Integer对象包含值为10在intVal变量中。这个父线程创建一个子线程,它调用intVal和接收它的父线程的Integer对象。执行上面代码你将会看到:Child 10。
 源码下载:git@github.com:owenwilliam/Thread.git

4.2线程局部变量(Thread-Local Variables)相关推荐

  1. 全链路跟踪之线程上下文Thread Local实战(完整源码)

    写在开头: 我是「猿码天地」,一个热爱技术.热爱编程的IT猿.技术是开源的,知识是共享的! 写博客是对自己学习的总结和记录,如果您对Java.分布式.微服务.中间件.Spring Boot.Sprin ...

  2. TLS(Thread Local Storage)问题demo

      C++11中的thread_local是C++存储期的一种,属于线程存储期.存储期定义C++程序中变量/函数的范围(可见性)和生命周期.C++程序中可用的存储期包括auto.register.st ...

  3. JVM线程本地分配缓冲区(Thread Local Allocation Buffer)TLAB详解

    最近在看java性能相关方面的书籍.然后在GC调优相关的部分出现了,线程本地分配缓冲区的名词,对于它的调优级为重要,所以就梳理一下这个到底是什么?为什么他对于JVM性能如此重要. 什么是JVM线程本地 ...

  4. thread local storage

    有时会需要这种模式,一个全局变量,需要在程序的任何地方都可以使用它,但是当这个变量出现在不同线程时,就要求系统将这个变量拷贝到各个线程中,这样的话,每个线程内部也可以随时访问本线程的全局变量,但是线程 ...

  5. Java线程局部变量ThreadLocal

    ThreadLocal基础 ThreadLocal类可以让每个线程绑定自己的值,它就像一个全局存放数据的盒子,盒子中可以存放每个线程的私有数据. ThreadLocal类只有一个无参的构造函数,因此实 ...

  6. Java小白的入门面试笔记--线程局部变量之灵魂四问

    1.ThreadLocal 是什么? ThreadLocal俗名叫做线程局部变量,就是由ThreadLocal通过set方法填充的变量,它是只属于当前的线程,对于其他的线程来说是隔离的,是当前线程独有 ...

  7. TLAB(Thread Local Allocation Buffer)

    TLAB是虚拟机在堆内存的eden划分出来的一块专用空间,是线程专属的.在虚拟机的TLAB功能启动的情况下,在线程初始化时,虚拟机会为每个线程分配一块TLAB空间,只给当前线程使用,这样每个线程都单独 ...

  8. Python基础之线程(Thread)

    进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行 ...

  9. 线程局部变量 ThreadLocal

    文章目录 线程局部变量 ThreadLocal ThreadLocal 的作用和目的 ThreadLocal 的应用场景 ThreadLocal 的使用方式 (1) 在关联数据类中创建 private ...

  10. 线程(Thread,ThreadPool)、Task、Parallel

    线程(Thread.ThreadPool) 线程的定义我想大家都有所了解,这里我就不再复述了.我这里主要介绍.NET Framework中的线程(Thread.ThreadPool). .NET Fr ...

最新文章

  1. 技术图文:如何理解C#的internal限制修饰符?
  2. 突发!Log4j 爆“核弹级”漏洞,Flink、Kafka等至少十多个项目受影响
  3. jQuery 核心 - noConflict() 方法,jQuery 文档操作 - detach() 方法
  4. isAssignableFrom和isInstance、instanceof
  5. linux c语言定时任务crontab,linux 定时任务 crontab相关(一)
  6. 杭电1260java实现
  7. PC SERVER 序列号查询
  8. C语言程序设计 | 结构体内存对齐,位段
  9. 自适应移动设备页面的设计
  10. python语法与java语法的区别_Python语言与java语法的异同之处
  11. C++字符串输入输出操作
  12. 服务器硬盘sas速度多少,R710服务器6块硬盘(SAS 300G 15000转)做完Raid5后读写速度没有一台普通台式机硬盘的读写速度快...
  13. 云操作系统OpenStack 优势与问题并存
  14. ensp-VRRP的配置
  15. 心形炫彩LED灯设计
  16. 450g带盖吐司配方_【最好吃的吐司记录450克的做法步骤图】偶尔小雨_下厨房
  17. ABR与ASBR区别
  18. 计算机累加器有加法器功能吗,累加器是什么_累加器的作用及原理介绍
  19. java毕业设计员工绩效考核系统分析与设计Mybatis+系统+数据库+调试部署
  20. electron-vue更新依赖

热门文章

  1. python - 日期处理模块
  2. 高校应该使用 Drupal 的10大理由
  3. ListIterator和Iterator的区别
  4. HCIE-Security Day10:6个实验理解VRRP与可靠性
  5. Linux常用基础命令3
  6. H3C和cisco单臂路由和三层交换机实现VLAN之间的互通
  7. 华三H3c 交换机 vlan Hybird端口配置
  8. centos服务器 常用命令
  9. python命令行tab实例小妙招
  10. windows 7 等 公文包 功能 作用 使用说明