06_张孝祥_多线程_ThreadLocal类及应用技巧
设计
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类及应用技巧相关推荐
- 11_张孝祥_多线程_线程锁技术
转载 Java并发编程:Lock locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---AbstractOwnableSynchroniz ...
- java 多线程 张孝祥_多线程11_张孝祥 java5的线程锁技术
本例子因为两个线程公用同线程中,使用同一个对象,实现了他们公用一把锁,实现了同一个方法的互斥. package locks; /** *会被打乱的效果 */ public class LockTest ...
- 16_张孝祥_多线程_同步工具CyclicBarrier与CountDownLatch
转载: CyclicBarrier的用法 CountDownLatch(倒计时计数器)使用说明 参考: CyclicBarrier和CountDownLatch区别 CyclicBarrier Cyc ...
- JAVA入门_多线程_邮局派发信件
JAVA入门_多线程_邮局派发信件 Postman package cn.campsg.java.experiment.entity;public class Postman {private Str ...
- 复习Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节
Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节 主要内容 Object类 Date类 DateFormat类 Calendar类 System类 Stri ...
- 第四章Java核心类库_多线程
第四章第五节Java核心类库_多线程 多线程 一.线程与进程 1.线程与进程 2.线程调度 二.同步与异步&并发与并行 1. 同步与异步 2. 并发与并行 三.继承Thread 1.代码块 2 ...
- 多线程Thread类创建多线程
package com.ajax; //多线程Thread类创建多线程 public class Example02 {public static void main(String[] args){n ...
- 多线程Runnable类创建多线程
package com.ajax; //多线程Runnable类创建多线程 public class Example01 {public static void main(String [] args ...
- 天天有毒_鸡汤文案类小程序源码
简介: 天天有毒_鸡汤文案类小程序源码 网盘下载地址: http://kekewl.net/oi8WRaw46rq0 图片:
最新文章
- 谷歌推出TFQ,一个可训练量子模型的机器学习框架
- mysql集群2台linux_安装配置基于两台服务器的MySQL集群(2)
- C# 条件语句 if else 、 switch case 及练习题解析
- 亚马逊:自动选择AI模型,进化论方法效率更高!
- 机器学习性能度量(2):错误接受率 (FAR), 错误拒绝率(FRR),EER计算方法,python实现
- 奇异值值分解。svd_推荐系统-奇异值分解(SVD)和截断SVD
- python将dataframe写入csv_Pandas dataframe数据写入文件和数据库
- java 固定长度队列_如何彻底搞懂 Java 数据结构?|CSDN 博文精选
- EasyCriteria已演变为uaiCriteria。 新名称和更多功能
- sklearn 线性回归linear regression做分类任务
- python使用缩进来体现-Python使用缩进来体现代码之间的逻辑关系。
- jdk帮助文档的获取
- Linux系统war包解压目录,linux系统下解压war包
- 如何删除顽固文件或文件夹?
- linux登陆提示密码过期,linux用户密码过期
- 无法启动程序,.dll不是有效的Win32应用程序
- nexus仓库数据完整迁移到新的nexus仓库
- linux替换变量字符串,linux shell 替换字符串的几种方法,变量替换${},sed,awk
- 连锁不平衡:linkage disequilibrium
- Android 8.0以上系统应用如何保活