设计

ThreadLocal并不是包含Map对象,而是这些特定于线程的值保存在Thread对象中,java.lang.Thread定义了变量:ThreadLocal.ThreadLocalMap threadLocals = null,当线程终止后,这些值会作为垃圾回收。

ThreadLocal.ThreadLocalMap中定义Entry[] table变量,Entry类定义为Entry(ThreadLocal k, Object v),因此是线程java.lang.Thread包含了所有的ThreadLocal及该ThreadLocal中该线程对应的值。

ThreadLocal.set()创建新的Entry对象,并保存到ThreadLocal.ThreadLocalMap变量Entry[] table
ThreadLocal.get()时,各线程从自己的ThreadLocalMap对象变量Entry[] table中取出与该ThreadLocal对应的Entry对象,并取出entry保存的值。

使用

JDK1.5提供了ThreadLocal类来方便实现线程范围内的数据共享,它的作用就相当于 05_张孝祥Java多线程线程范围内共享变量的概念与作用 中的Map(内部并不是Map),也就是让每个线程拥有自己的值

一个ThreadLocal对象只能记录一个线程内部的一个共享变量,需要记录多个共享数据,可以创建多个ThreadLocal对象,或者将这些数据进行封装,将封装后的数据对象存入ThreadLocal对象中。

线程结束后也可以自动释放相关的ThreadLocal变量,也可以调用ThreadLocal.remove()方法用来更快释放内存。

代码

下面用ThreadLocal类实现,替代 05_张孝祥Java多线程线程范围内共享变量的概念与作用 实现

import java.util.Random;  public class ThreadLocalTest {  private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();  public static void main(String[] args) {  //启动两个线程  for (int i = 0; i < 2; i++) {  new Thread(new Runnable() {  @Override  public void run() {  //创建每个线程私有的变量  int data = new Random().nextInt(100);  System.out.println(Thread.currentThread().getName()+" has put data: "+data);  //往local里面设置值  threadLocal.set(data);  new A().get();  new B().get();  }  }).start();  }  }  static class A{  public void get(){  int data =threadLocal.get();  System.out.println("A from "+Thread.currentThread().getName()+" has get data: "+data);  }  }static class B{  public void get(){  int data =threadLocal.get();  System.out.println("B from "+Thread.currentThread().getName()+" has get data: "+data);  }  }
}  

假设需要保存不止一个值,可以把其他属性的值打包成一个类,然后将该类设置成ThreadLocal的值。

下面代码中,在类MyThreadLocalScopeDate里面定义了一个静态变量Map,用来保存所有线程创建的MyThreadLocalScopeDate,并使用单例使得不管多少线程都只创建一个MyThreadLocalScopeDate对象。

import java.util.Random;  public class ThreadLocalTest {  private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();  public static void main(String[] args) {  //启动两个线程  for (int i = 0; i < 2; i++) {  new Thread(new Runnable() {  @Override  public void run() {  //创建每个线程私有的变量  int data = new Random().nextInt(100);  System.out.println(Thread.currentThread().getName()+" has put data: "+data);  //往local里面设置值  threadLocal.set(data);  //获取自己线程的MyThreadLocalScopeDate实例对象  MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance();  myData.setName("name"+data);  myData.setAge(data);  new A().get();  new B().get();  }  }).start();  }  }  static class A{  public void get(){  int data =threadLocal.get();  System.out.println("A from "+Thread.currentThread().getName()+" has get data: "+data);  MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance();  System.out.println("A from "+Thread.currentThread().getName()+" has get MyThreadLocalScopeDate name: "+myData.getName()+" , age: "+myData.getAge());  }  }  static class B{  public void get(){  int data =threadLocal.get();  System.out.println("B from "+Thread.currentThread().getName()+" has get data: "+data);  MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance();  System.out.println("B from "+Thread.currentThread().getName()+" has get MyThreadLocalScopeDate name: "+myData.getName()+" , age: "+myData.getAge());  }  }
}  class MyThreadLocalScopeDate{//单例模式  private MyThreadLocalScopeDate(){};//构造方法私有化  private static ThreadLocal<MyThreadLocalScopeDate> map = new ThreadLocal<MyThreadLocalScopeDate>();//封装MyThreadLocalScopeDate是线程实现范围内共享  //思考AB两个线程过来的情况 自己分析 AB都需要的自己的对象 没有关系 所以不需要同步 如果有关系就需要同步了  public static /*synchronized*/MyThreadLocalScopeDate getThreadInstance(){  MyThreadLocalScopeDate instance =map.get();  if(instance==null){  instance = new MyThreadLocalScopeDate();  map.set(instance);  }  return instance;  }  private String name;  private int age;  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }
}

参考

06.ThreadLocal类及应用技巧
正确理解ThreadLocal
多线程06_张孝祥-ThreadLocal类及应用技巧

06_张孝祥_多线程_ThreadLocal类及应用技巧相关推荐

  1. 11_张孝祥_多线程_线程锁技术

    转载 Java并发编程:Lock locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---AbstractOwnableSynchroniz ...

  2. java 多线程 张孝祥_多线程11_张孝祥 java5的线程锁技术

    本例子因为两个线程公用同线程中,使用同一个对象,实现了他们公用一把锁,实现了同一个方法的互斥. package locks; /** *会被打乱的效果 */ public class LockTest ...

  3. 16_张孝祥_多线程_同步工具CyclicBarrier与CountDownLatch

    转载: CyclicBarrier的用法 CountDownLatch(倒计时计数器)使用说明 参考: CyclicBarrier和CountDownLatch区别 CyclicBarrier Cyc ...

  4. JAVA入门_多线程_邮局派发信件

    JAVA入门_多线程_邮局派发信件 Postman package cn.campsg.java.experiment.entity;public class Postman {private Str ...

  5. 复习Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节

    Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节 主要内容 Object类 Date类 DateFormat类 Calendar类 System类 Stri ...

  6. 第四章Java核心类库_多线程

    第四章第五节Java核心类库_多线程 多线程 一.线程与进程 1.线程与进程 2.线程调度 二.同步与异步&并发与并行 1. 同步与异步 2. 并发与并行 三.继承Thread 1.代码块 2 ...

  7. 多线程Thread类创建多线程

    package com.ajax; //多线程Thread类创建多线程 public class Example02 {public static void main(String[] args){n ...

  8. 多线程Runnable类创建多线程

    package com.ajax; //多线程Runnable类创建多线程 public class Example01 {public static void main(String [] args ...

  9. 天天有毒_鸡汤文案类小程序源码

    简介: 天天有毒_鸡汤文案类小程序源码 网盘下载地址: http://kekewl.net/oi8WRaw46rq0 图片:

最新文章

  1. 谷歌推出TFQ,一个可训练量子模型的机器学习框架
  2. mysql集群2台linux_安装配置基于两台服务器的MySQL集群(2)
  3. C# 条件语句 if else 、 switch case 及练习题解析
  4. 亚马逊:自动选择AI模型,进化论方法效率更高!
  5. 机器学习性能度量(2):错误接受率 (FAR), 错误拒绝率(FRR),EER计算方法,python实现
  6. 奇异值值分解。svd_推荐系统-奇异值分解(SVD)和截断SVD
  7. python将dataframe写入csv_Pandas dataframe数据写入文件和数据库
  8. java 固定长度队列_如何彻底搞懂 Java 数据结构?|CSDN 博文精选
  9. EasyCriteria已演变为uaiCriteria。 新名称和更多功能
  10. sklearn 线性回归linear regression做分类任务
  11. python使用缩进来体现-Python使用缩进来体现代码之间的逻辑关系。
  12. jdk帮助文档的获取
  13. Linux系统war包解压目录,linux系统下解压war包
  14. 如何删除顽固文件或文件夹?
  15. linux登陆提示密码过期,linux用户密码过期
  16. 无法启动程序,.dll不是有效的Win32应用程序
  17. nexus仓库数据完整迁移到新的nexus仓库
  18. linux替换变量字符串,linux shell 替换字符串的几种方法,变量替换${},sed,awk
  19. 连锁不平衡:linkage disequilibrium
  20. Android 8.0以上系统应用如何保活

热门文章

  1. 一是数据库,数据库是一
  2. 矿泉水溴酸盐超标如何解决?除溴酸盐设备有哪些?
  3. Appium安装配置注意事项
  4. C++编写的简易宝可梦对战小游戏
  5. Flutter-分段滑块
  6. CSDN排名第一的人--2019
  7. CAJViewer浏览器---任意版本下载
  8. 根据经纬度坐标计算两点的距离
  9. n!阶乘末尾有多少个零0
  10. Android adb cannot connect to deamon