1.7 ThreadLocal的原理和使用详解
目录
一、why:为什么要用ThreadLocal
1.1示例:不使用ThreadLocal,使用static,每个值修改同一个变量,产生错误
1.2运行结果,可能有几种可能性:
1.3使用ThreadLocal
1.4结果:都是2
二、ThreadLocal的使用
2.1ThreadLocal类接口很简单,常用的有4个方法
2.2remove的测试
2.3执行结果
三、ThreadLocal初始化方法的使用
1、实现方法initialValue
2、通过lomoba表达式
四、ThreadLocal在线程中的使用,即怎么让多个线程使用threadLocal
1、线程对象内部自定义threadLocal
2、通过构造函数传递进线程的ThreadLocal变量
一、why:为什么要用ThreadLocal
1.1示例:不使用ThreadLocal,使用static,每个值修改同一个变量,产生错误
/*** 不使用ThreadLocal共同使用变量,使用static,每个值修改同一个变量,产生错误* @author: honry.guan* @create: 2020-06-07 18:53**/
public class NoThreadLocalTest extends Thread{private static int num = 1;@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+": 开始执行,num = "+num);num = num + 1;System.out.println(Thread.currentThread().getName()+" 结束,num = "+num);}public static void main(String[] args) {for (int i = 0; i < 3; i++) {NoThreadLocalTest t = new NoThreadLocalTest();t.start();}}
}
1.2运行结果,可能有几种可能性:
Thread-1: 开始执行,num = 1
Thread-0: 开始执行,num = 1
Thread-0 结束,num = 3
Thread-2: 开始执行,num = 1
Thread-1 结束,num = 2
Thread-2 结束,num = 4
也有可能是:
Thread-1: 开始执行,num = 1
Thread-2: 开始执行,num = 1
Thread-2 结束,num = 2
Thread-0: 开始执行,num = 1
Thread-0 结束,num = 4
Thread-1 结束,num = 4
1.3使用ThreadLocal
public class NoThreadLocalTest extends Thread{private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){@Overrideprotected Integer initialValue() {return 1;}};@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+": 开始执行,num = "+num.get());num.set(num.get() + 1);System.out.println(Thread.currentThread().getName()+" 结束,num = "+num.get());}public static void main(String[] args) {for (int i = 0; i < 3; i++) {NoThreadLocalTest t = new NoThreadLocalTest();t.start();}}
}
1.4结果:都是2
Thread-0: 开始执行,num = 1
Thread-2: 开始执行,num = 1
Thread-2 结束,num = 2
Thread-1: 开始执行,num = 1
Thread-0 结束,num = 2
Thread-1 结束,num = 2
二、ThreadLocal的使用
2.1ThreadLocal类接口很简单,常用的有4个方法
• void set(Object value):设置当前线程的线程局部变量的值。
• public Object get():该方法返回当前线程所对应的线程局部变量。
• public void remove():移除变量,如果最开始是1,通过set修改之后,调用remove之后,get出来的值又变成1
• protected Object initialValue():初始,第一次调用set或get才执行,并且仅执行一次。
2.2remove的测试
public class NoThreadLocalTest extends Thread{private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){@Overrideprotected Integer initialValue() {return 1;}};@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+": 开始执行,num = "+num.get());num.set(num.get() + 1);System.out.println(Thread.currentThread().getName()+" 结束,num = "+num.get());num.remove();System.out.println(Thread.currentThread().getName()+" 结束remove之后,num = "+num.get());}public static void main(String[] args) {for (int i = 0; i < 3; i++) {NoThreadLocalTest t = new NoThreadLocalTest();t.start();}}
}
2.3执行结果
Thread-1: 开始执行,num = 1
Thread-2: 开始执行,num = 1
Thread-0: 开始执行,num = 1
Thread-0 结束,num = 2
Thread-2 结束,num = 2
Thread-1 结束,num = 2
Thread-1 结束remove之后,num = 1
Thread-2 结束remove之后,num = 1
Thread-0 结束remove之后,num = 1
三、ThreadLocal初始化方法的使用
1、实现方法initialValue
private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){@Overrideprotected Integer initialValue() {return 1;}
};
2、通过lomoba表达式
ThreadLocal<Integer> num = ThreadLocal.withInitial(()->1);
四、ThreadLocal在线程中的使用,即怎么让多个线程使用threadLocal
(我刚学的时候一直被这个事情困扰,自己手写几次之后明白)
只要在线程run方法中,调用ThreadLocal的get或者set,不管是线程对象内部自定义threadLocal,还是通过构造函数传递进线程的ThreadLocal变量。
1、线程对象内部自定义threadLocal
public class NoThreadLocalTest extends Thread{private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){@Overrideprotected Integer initialValue() {return 1;}};@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+": 开始执行,num = "+num.get());num.set(num.get() + 1);System.out.println(Thread.currentThread().getName()+" 结束,num = "+num.get());num.remove();System.out.println(Thread.currentThread().getName()+" 结束remove之后,num = "+num.get());}public static void main(String[] args) {for (int i = 0; i < 3; i++) {NoThreadLocalTest t = new NoThreadLocalTest();t.start();}}
}
2、通过构造函数传递进线程的ThreadLocal变量
public class NoThreadLocalTest extends Thread{private ThreadLocal<Integer> num ;public NoThreadLocalTest(ThreadLocal<Integer> num) {this.num = num;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+": 开始执行,num = "+num.get());num.set(num.get() + 1);System.out.println(Thread.currentThread().getName()+" 结束,num = "+num.get());num.remove();System.out.println(Thread.currentThread().getName()+" 结束remove之后,num = "+num.get());}public static void main(String[] args) {ThreadLocal<Integer> num = ThreadLocal.withInitial(()->1);}
}
此时不论什么一个线程能够并发访问这个变量,对它进行写入、读取操作,都是线程安全的。
1.7 ThreadLocal的原理和使用详解相关推荐
- python的编程模式-Python设计模式之状态模式原理与用法详解
本文实例讲述了Python设计模式之状态模式原理与用法.分享给大家供大家参考,具体如下: 状态模式(State Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类 ...
- DeepLearning tutorial(1)Softmax回归原理简介+代码详解
FROM: http://blog.csdn.net/u012162613/article/details/43157801 DeepLearning tutorial(1)Softmax回归原理简介 ...
- DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解
FROM:http://blog.csdn.net/u012162613/article/details/43221829 @author:wepon @blog:http://blog.csdn.n ...
- DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解
FROM: http://blog.csdn.net/u012162613/article/details/43225445 DeepLearning tutorial(4)CNN卷积神经网络原理简介 ...
- Nginx(二):反向代理原理 与 配置文件详解
相关阅读: Nginx(一):Nginx原理概述 与 安装步骤详解 Nginx(二):反向代理原理 与 配置文件详解 Nginx(三):负载均衡策略 与 Nginx静态服务器 Nginx(四):Ngi ...
- java linkedlist实例_Java Linkedlist原理及实例详解
这篇文章主要介绍了Java Linkedlist原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 定义:linkedlist属于链表结构 ...
- 【多元域除法】多项式除法电路原理及MATLAB详解
关注公号[逆向通信猿]更精彩!!! 关于二元域上的两个元素的加法和乘法.多项式除法,在之前的博客 [有限域除法]二元多项式除法电路原理及MATLAB详解 子程序:sub_poly_div.m [有限域 ...
- 【多元域乘法】多项式乘法电路原理及MATLAB详解
关注公号[逆向通信猿]更精彩!!! 关于二元域上的两个元素的乘法.多项式除法,在之前的博客 [有限域除法]二元多项式除法电路原理及MATLAB详解 子程序:sub_poly_div.m [有限域元素加 ...
- java设计模式观察者模式吗_Java设计模式之观察者模式原理与用法详解
Java设计模式之观察者模式原理与用法详解 本文实例讲述了Java设计模式之观察者模式原理与用法.分享给大家供大家参考,具体如下: 什么是观察者模式 可以这么理解: 观察者模式定义了一种一对多的依赖关 ...
最新文章
- 鸿蒙程序如何上传,鸿蒙应用程序流转的实现
- 如何查看dede版本信息
- linux之uniq 命令详解
- python学了有什么用处-Python主要用途是哪些,跟机器学习等有啥关系呢?
- 虚拟机无法远程连接的问题
- Android Studio 添加 Genymotion插件
- 波士顿动力机器人全体出动,奉上新年之舞!
- content属性的4种用途
- 关于PHP代码的开始和结束标签书写,关于PHP结束标签?gt;的使用细节
- 计组之指令系统:3、CISC和RISC
- STM32那点事(2)_时钟树(下)
- IO流和集合的交集Properties类的介绍。
- ip变更 mysql无法启动_ubuntu mysql 更改IP导致mysql无法启动
- 小白记事本--链表--loading
- spring加载属性(properties)文件
- 2021美赛成绩查询证书下载
- c语言摄氏度单位ascii,请问温度标识 ℃,ASCII码怎么写
- 批处理打开/关闭休眠
- 电脑c盘分区太小如何可以扩大,电脑c盘不够用了,如何给电脑分区
- 银联支付前端页面跳转
热门文章
- 兰州大学信息与计算机科学硕,兰州大学信息科学与工程学院
- 关于LCD1602单独清除某一行的问题
- Fresco+Recycleview+OKhttp+Retrofit
- REST模式:POST,GET,PUT,DELETE,PATCH的含义与区别
- php 查询功能,php如何实现查询功能实现
- 笔记本电池不行 省电妙招
- plt画网格图_matplotlib子图与多种图形绘制
- 为什么建议大家使用 Linux 开发?有那么爽吗?
- c语言求对应学号的总成绩,c语言 求大神编程。定义一个学生结构体,包括学号、姓名、年龄、成绩。1、要求输入五个学生相应的信息,求学生成绩总和。2、输入一个学生学号,把该学生全部信息输出。...
- html只显示一句话_您所说的话:如何最大化多显示器设置