ThreadLocal使用全解
一、何为ThreadLocal
1、ThreadLocal的含义
ThreadLocal,即线程变量,是一个以ThreadLocal对象为键,任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
2、ThreadLocal的实用意义
每个线程拥有自己的局部变量毫无疑问比使用全局变量好,因为局部的变量只有县城自己能看见,而不会影响到其他线程。ThreadLocal本身能被多个线程共享使用,并且又能达到线程安全的目的。常用的就是get、set、initialValue等方法。
3、使用ThreadLocal前你必须知道的
JDK建议将ThreadLocal定义为private static类型。
ThreadLocal最常用的地方就是为每个线程绑定一个数据连接、HTTP请求、用户身份信息等,这样一个线程的所有调用到的方法都可以非常方便地访问这些资源。
二、ThreadLocal的使用
1、创建和初始化ThreadLocal
我们只需直接用new的方式创建ThreadLocal变量,并使用一个泛型参数指定ThreadLocal的类型。如果ThreadLocal的初始值不被设定,它的默认初始值将被设定为null,如果要更改初始值,我们通常有两种方法:
- 使用实现了initialValue的匿名内部类
- 使用ThreadLocal的类方法withInitial(),参数使用lambda表达式
这两种方法都是在new一个ThreadLocal对象时使用。
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
//如果要更改初始值
//方法一 需要一个继承了ThreadLocal父类,重写了initialValue方法的类,用它来创建ThreadLocal类对象
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>(){ //这里使用匿名内部类
@Override
protected Integer initialValue() {
return 200; //初始化的值由null变成200
}
};
//方法二 使用withIntial方法
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->200);
2、获取和设置ThreadLocal的值
使用get和set方法即可
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->200);
//获取值
System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());//get获取值
//设置值
threadLocal.set(99);//set设置值
三、ThreadLocal的一个简单示例
public class ThreadLocalTest {
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->1);
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread(new MyRun()).start();
}
}
//内部类
public static class MyRun implements Runnable{
@Override
public void run() {
Integer left = threadLocal.get();
System.out.println(Thread.currentThread().getName()+"得到了-->"+left);
threadLocal.set(left-1);
System.out.println(Thread.currentThread().getName()+"还剩下-->"+threadLocal.get());
}
}
}
四、ThreadLocal的上下文环境分析
注意,在ThreadLocal的使用中,get到的值的来源有以下规律
- 在构造器中试图get:哪个线程调用了构造器就get到哪个线程的ThreadLocal的值
- 在run方法中或其调用的方法中试图get:get该线程自己的ThreadLocal的值
以下是一个示例
public class ThreadLocalTest {
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->1);
public static void main(String[] args) {
new Thread(new MyRun()).start(); //如果构造器中有读写ThreadLocal,这里设置的是main线程
}
//内部类
public static class MyRun implements Runnable{
public MyRun() {
//构造器是哪里调用就属于哪里。这里是main调用的,所以设置和打印的都是main的ThreadLocal的值
threadLocal.set(100);
System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
//new Thread(new MyRun()).start(); //如果在这里又new一个MyRun对象,就要调用构造器,其中set和get的,就是这里这个线程的ThreadLocal的值
}
}
}
五、ThreadLocal和Synchronized的对比
ThreadLocal和Synchronized都是为了解决多线程中相同变量的访问冲突问题,不同的点是
- Synchronized是通过线程等待,牺牲时间来解决访问冲突
- ThreadLocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突,并且相比于Synchronized,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值。
正因为ThreadLocal的线程隔离特性,使他的应用场景相对来说更为特殊一些。在android中Looper、ActivityThread以及AMS中都用到了ThreadLocal。当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal。
ThreadLocal使用全解的更多相关文章
- Mybatis系列全解(六):Mybatis最硬核的API你知道几个?
封面:洛小汐 作者:潘潘 2020 年的大疫情,把世界撕成几片. 时至今日,依旧人心惶惶. 很庆幸,身处这安稳国, 兼得一份安稳工. · 东家常讲的一个词:深秋心态 . 大势时,不跟风.起哄, 萧条时 ...
- 易全解token获取
//易全解app string strClientID = "2016061711434943493606"; string str ...
- IOS-UITextField-全解
IOS-UITextField-全解 //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame: ...
- 什么是JavaScript闭包终极全解之一——基础概念
本文转自:http://www.cnblogs.com/richaaaard/p/4755021.html 什么是JavaScript闭包终极全解之一——基础概念 “闭包是JavaScript的一大谜 ...
- Sql Server函数全解<五>之系统函数
原文:Sql Server函数全解<五>之系统函数 系统信息包括当前使用的数据库名称,主机名,系统错误消息以及用户名称等内容.使用SQL SERVER中的系统函数可以在需要的时候获取这些 ...
- Sql Server函数全解<四>日期和时间函数
原文:Sql Server函数全解<四>日期和时间函数 日期和时间函数主要用来处理日期和时间值,本篇主要介绍各种日期和时间函数的功能和用法,一般的日期函数除了使用date类型的参数外, ...
- 九度oj题目&吉大考研11年机试题全解
九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码). http://ac.jobdu.com/problem.php?pid=11 ...
- js系列教程2-对象、构造函数、对象属性全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...
- js系列教程1-数组操作全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...
随机推荐
- 【Java】集合框架(List Set Map)
文章目录 集合框架 List(列表) ArrayList 案例 Set HashSet 案例 iterator(迭代器) Map HashMap 案例 集合总结 参考资料 重新搞一波 复习巩固 简单记 ...
- QPinter 常用绘制图像的方法
阅读本文大概需要 3 分钟 我们在开发软件的过程中,绘制图像功能必不可少,使用 Qt 绘制图像时非常简单,只需要传递几个参数就可以实现功能,在 Qt 中绘制图像的 api有好几个 void drawI ...
- 【ORA】ORA-27090: Unable to reserve kernel resources for asynchronous disk I/O
操作系统是CentOS 5.11 数据库 10.2.0.5.0 晚上查看数据库,发现数据库报错查看相关的trace文件内容如下: *** SERVICE NAME:(SYS$BACKGROUND) 2 ...
- 记录一下 ThreadLocal 与 WeakReference
ThreadLocal & WeakReference Thread整体的模块图 Thread -> ThreadLocalMap 对于继承了 WeakReference Entry本身 ...
- 全网最详细的PyCharm+Anaconda的安装。
目录 PyCharm的安装 一.下载安装包 1.安装网站 2.在导航栏输入网址回车 3.点击 DOWNLOAD. 4.它有专业版和社区版,我们下载社区版就可以使用了.(专业版要收费) 二.安装过程 5 ...
- ECharts特效-折线图上一个光点来回移动
参考地址:https://www.makeapie.com/editor.html?c=xxxcG6NGk0 效果图打开上面的网址就可以看到. 核心代码如下,该效果实现的难点是数据的封装,还有eval ...
- es_python_操作
获取es索引 https://www.itranslater.com/qa/details/2583886977221264384
- 无法获取 vmci 驱动程序版本: 句柄无效。 驱动程序 vmci.sys 版本不正确。请尝试重新安装 VMware Workstation。 打开模块DevicePowerOn电源失败。
1.别打开电源,然后到虚拟机安装文件夹内.2.找到你的虚拟机系统文件中后缀为vmx的文件,右击用记事本或者Notepad++打开.2.搜索找到vmci0.present='TRUE',字段,把true ...
- jQuery 实现复制功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- jQuery 文本段落展开和折叠效果
jQuery 文本段落展开和折叠效果 <!DOCTYPE html> <head> <meta http-equiv="Content-Type" c ...