JAVA多线程学习五:线程范围内共享变量&ThreadLocal
一、概念
可以将每个线程用到的数据与对应的线程号存放到一个map集合中,使用数据时从这个集合中根据线程号获取对应线程的数据,就可以实现线程范围内共享相同的变量。
二、代码
Runnable中的run()方法里面执行Thread.currentThread()都会对应当前Runnable对应的线程,因此A、B中对应的Thread.currentThread()对应所在的Runnable对应的线程

- public class ThreadScopeShareData {
- private static Map<Thread, Integer> threadData = new HashMap<Thread, 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();
- System.out.println(Thread.currentThread().getName()
- + " has put data :" + data);
- threadData.put(Thread.currentThread(), data);
- new A().get();
- new B().get();
- }
- }).start();
- }
- }
- static class A{
- public void get(){
- int data = threadData.get(Thread.currentThread());
- System.out.println("A from " + Thread.currentThread().getName()
- + " get data :" + data);
- }
- }
- static class B{
- public void get(){
- int data = threadData.get(Thread.currentThread());
- System.out.println("B from " + Thread.currentThread().getName()
- + " get data :" + data);
- }
- }
- }

三、ThreadLocal
JDK1.5提供了ThreadLocal类来方便实现线程范围内的数据共享,它的作用就相当于前面中的Map(内部并不是Map),也就是让每个线程拥有自己的值
一个ThreadLocal对象只能记录一个线程内部的一个共享变量,需要记录多个共享数据,可以创建多个ThreadLocal对象,或者将这些数据进行封装,将封装后的数据对象存入ThreadLocal对象中。
线程结束后也可以自动释放相关的ThreadLocal变量,也可以调用ThreadLocal.remove()方法用来更快释放内存。
代码:

- 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对象。

- 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;
- }
- }

出处:https://www.cnblogs.com/pony1223/p/9251641.html
JAVA多线程学习五:线程范围内共享变量&ThreadLocal的更多相关文章
- JAVA多线程提高三:线程范围内共享变量&ThreadLocal
今天我们学习的是如何在线程自己的范围内达到变量数据的共享,而各个线程之间又是互相独立开来,各自维护的,即我们说的ThreadLocal的作用. 一.概念 可以将每个线程用到的数据与对应的线程号存放到一 ...
- Java多线程学习篇——线程的开启
随着开发项目中业务功能的增加,必然某些功能会涉及到线程以及并发编程的知识点.笔者就在现在的公司接触到了很多软硬件结合和socket通讯的项目了,很多的功能运用到了串口通讯编程,串口通讯编程的安卓端就是 ...
- JAVA多线程学习七-线程池
为什么用线程池 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率 例如: 记创建线程消耗时间T1,执行任务消耗时间T2,销毁线程消耗时间T3 如果T1+T3> ...
- Java多线程学习之线程的取消与中断机制
任务和线程的启动很容易.在大多数情况下我们都会让他们运行直到结束,或是让他们自行停止.但是,有时我们希望提前结束任务或是线程,可能是因为用户请求取消,或是线程在规定时间内没有结束,或是出现了一些问题迫 ...
- JAVA多线程学习十一-线程锁技术
前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...
- Java多线程学习总结--线程概述及创建线程的方式(1)
在Java开发中,多线程是很常用的,用得好的话,可以提高程序的性能. 首先先来看一下线程和进程的区别: 1,一个应用程序就是一个进程,一个进程中有一个或多个线程.一个进程至少要有一个主线程.线程可以看 ...
- Java多线程学习之线程池源码详解
0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...
- Java多线程学习(三)---线程的生命周期
线程生命周期 摘要: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞 ...
- Java多线程学习(二)---线程创建方式
线程创建方式 摘要: 1. 通过继承Thread类来创建并启动多线程的方式 2. 通过实现Runnable接口来创建并启动线程的方式 3. 通过实现Callable接口来创建并启动线程的方式 4. 总 ...
随机推荐
- Inverse/Implicit Function Theorem
目录 4.1 The Inverse Function Theorem The Implicit Function Theorem 4.3 Curves and Surfaces 4.4 The Mo ...
- Towards Deep Learning Models Resistant to Adversarial Attacks
目录 概 主要内容 Note Madry A, Makelov A, Schmidt L, et al. Towards Deep Learning Models Resistant to Adver ...
- Least Angle Regression
目录 引 一些基本的假设 LARS算法 算法 与别的方法结合 LARS与LASSO的关系 LARS 与 Stagewise 代码 Efron B, Hastie T, Johnstone I M, e ...
- 三角网格上的寻路算法Part.1—Dijkstra算法
背景 最近在研究中产生了这样的需求:在三角网格(Mesh)表示的地形图上给出两个点,求得这两个点之间的地面距离,这条距离又叫做"测地线距离(Geodesic)".计算三角网格模型表 ...
- [数据结构]FHQ-Treap
前言(个人评价FHQ-Treap) 这是一个巨佬(名叫范浩强)在冬令营交流的时候提出的数据结构(FHQ:\(\text{你干嘛非要旋转呢?Think Functional!}\))(可以看出FHQ大佬 ...
- LC 只出现一次的数字
Given a non-empty array of integers nums, every element appears twice except for one. Find that sing ...
- spring boot 打包war后 部署到外部 tomcat 的具体正确操作【包括修改端口 与 去除请求路径的工程名】
1.前言 工程做好了,总不能放在idea运行吧?不然怎么把项目放到云服务器呢?[这一篇随笔不讲解发布的云服务器的操作,在其他随笔有详细记载.] 解决的方案是把springboot 工程 打包成war文 ...
- Lucene8.5.x全文检索工具
本文的资源展示: hotword:是热词的文本,比如不是词语的中文,但是是什么人名或者公司名称的词语,需要分词成一个词语的将需要的加入hotword.dic stopword:无意义的词放入的词典,或 ...
- Java使用poi实现Word添加水印(仅支持后缀为.docx格式)
最近要做电子合同,客户提出为了安全性要将合同中都添加水印,这个之前在网上看到过,貌似使用POI很好加.去网上一搜发现,清一色的只有一篇文章,并且这段代码是用不了的:在文章下边的评论里也发现都说用不了, ...
- 【C++】自定义数据类型
自定义数据类型 标签:c++ 目录 自定义数据类型 一.结构体 定义方法: 特点: 成员访问方式: 初始化: 结构数组 指针和动态内存分配: 结构变量作为函数参数: 二.联合 定义方法: 特点: 举例 ...