ThreadLocal快速了解一下
欢迎点赞阅读,一同学习交流,有疑问请留言 。
GitHub上也有开源 JavaHouse 欢迎star
1 引入
在Java8里面,ThreadLocal 是一个泛型类。这个类可以提供线程变量。每个线程都有自己的变量。这意味着什么?每一个线程都有自己的资源,就像在现实生活中,每一个程序员都有自己的一个对象,不用去竞争,绝对的线程安全啊。那么 ThreadLocal 究竟怎么用呢?
2 类的说明
* This class provides thread-local variables. These variables differ from
* their normal counterparts in that each thread that accesses one (via its
* {@code get} or {@code set} method) has its own, independently initialized
* copy of the variable. {@code ThreadLocal} instances are typically private
* static fields in classes that wish to associate state with a thread (e.g.,
* a user ID or Transaction ID).
这是 ThreadLocal 类上面的说明。大概意思是提供线程变量,通常是被 static fields 修饰。
3 创建他
创建 ThreadLocal 有两种方法,一种通过原始的无参构造器, 另一种是使用Java8的 lamaba 表达式。
3.1 无参构造器
源码
/**
* Creates a thread local variable.
* @see #withInitial(java.util.function.Supplier)
*/
public ThreadLocal() {
}
使用并初始化
private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue(){
return 1;
}
};
3.2 lamaba 表达式
/**
* Creates a thread local variable. The initial value of the variable is
* determined by invoking the {@code get} method on the {@code Supplier}.
*
* @param <S> the type of the thread local's value
* @param supplier the supplier to be used to determine the initial value
* @return a new thread local variable
* @throws NullPointerException if the specified supplier is null
* @since 1.8
*/
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
return new SuppliedThreadLocal<>(supplier);
}
使用并初始化
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> 1);
其实使用如果使用 IDEA 的话, 编译器也会提示可以有 lamaba。 但是看看里面的源码还是挺有意思的。
4 getter() 方法
/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
这里可以看到 Thread.currentThread,获取了当前线程,还有 ThreadLocalMap 这个类,他是一个哈希结构(key-value)。getMap() 方法通过当前线程去获取他。 然后从再通过 this 关键字作为key,得到相应的值value。当然如果为空,就会返回初始化的值。
5 setter() 方法
什么情况下不会返回初始化的默认值呢,答案就是调用了setter() 方法。先看源码
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
大概意思就是将当前线程作为key, 要设的值作为 value 放在 ThreadLocalMap 这个哈希结构中。看到这里,就知道为什么说 ThreadLocal 可以提供线程变量了。他讲每个线程都分开存储,每个线程都有自己的独立资源,不存在资源共享的情况,所以线程安全。
6 内存泄漏
每个线程变量都放进一个 ThreadLocalMap 里面,不会有内存问题吗。我截取一部分源码
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
这里可以看到了 WeakReference 这个类,可以知道 ThreadLocalMap 类是一个弱引用,按道理来说,一般执行完线程,就会被虚拟机的垃圾回收机制回收了。但是,真的是这样的吗。如果是线程池环境里面,线程一直存在,那么 ThreadLocal 就会变成起强引用了,不能被回收了。所以有内存泄漏问题。
那现在就是 remove() 方法出场的时候了。按照字面意思,可以知道,该方法可以清掉线程变量资源,事实也是这样。所以,在程序的最后,最好调用一下 emove() 方法,防止内存泄漏。
参考
《实战Java高并发程序设计》
ThreadLocal 源码代
关注微信公众号,随时移动端阅读

ThreadLocal快速了解一下的更多相关文章
- ThreadLocal的应用与实现原理
本文对ThreadLocal的分析基于JDK 8. 本文大纲 1. ThreadLocal快速上手 2. ThreadLocal应用场景 3. TheadLocal set与get方法简析 4. Th ...
- ThreadLocal 是什么鬼?用法、源码一锅端
ThreadLocal 是一个老生常谈的问题,在源码学习以及实际项目研发中,往往都能见到它的踪影,用途比较广泛,所以有必要深入一番. 敢问,ThreadLocal 都用到了哪里?有没有运用它去解决过业 ...
- 【Java】ThreadLocal细节分析
ThreadLocal通过中文解释就是线程本地变量,是线程的一个局部变量.根据哲学家黑格尔“的存在即合理”的说法,ThreadLocal的出现肯定是有它的意义,它的出现也是因为多线程的一个产物.Thr ...
- SpringMVC:学习笔记(1)——理解MVC及快速入门
SprigMVC-理解MVC及快速入门 说明: 传统MVC-->JSPModel2-->Front Controller + Application Controller + Page C ...
- 阿里巴巴Java开发手册快速学习
Java作为一门名副其实的工业级语言,语法友好,学习简单,大规模的应用给代码质量的管控带来了困难,特别是团队开发中,开发过程中的规范会直接影响最终项目的稳定性. 善医者“未有形而除之”,提高工程健壮性 ...
- Java核心编程快速学习
Java核心编程部分的基础学习内容就不一一介绍了,本文的重点是JAVA中相对复杂的一些概念,主体内容如下图所示. 反射reflect是理解Java语言工作原理的基础,Java编译器首先需要将我们编写的 ...
- Mybatis第一篇【介绍、快速入门、工作流程】
什么是MyBatis MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...
- ThreadLocal源码分析:(一)set(T value)方法
在ThreadLocal的get(),set()的时候都会清除线程ThreadLocalMap里所有key为null的value. 而ThreadLocal的remove()方法会先将Entry中对k ...
- 第一阶段——CentOS6_Python3.6.1笔记(尚学堂-Python基础快速入门)+ 【补充】麦子-Python程序入门与进阶
虚拟机环境: 设置网络 .修改网络地址 .设置网卡为nat模式 .确保物理机启动dhcp.net服务 .编辑文件:vim /etc/sysconfig/network-scripts/ifcfg-et ...
随机推荐
- Git学习笔记----基础运用
安装Git Windows: 进入官网下载或百度网盘下载 Git(V2.23_x64) 提取码:uf2x Ubuntu: sudo apt-get -install git 安装完成之后打开git命令 ...
- 爬虫之selenium爬取京东商品信息
import json import time from selenium import webdriver """ 发送请求 1.1生成driver对象 2.1窗口最大 ...
- [考试反思]0921csp-s模拟测试49:困顿
太弱.还是太弱. 拉不开分差,离第一机房分数线估计还是300多分. 但是,还是要骂:XX出题人. 部分分非常少且没有意义,T1基本只有0/纯暴力20/100三个档, T2正解是n2但是n3一分不给,还 ...
- [专题总结]AC自动机
其实前面的模板也不是1A,我在题库里提前做过,也不必在意罚时,刚开始我在做别的专题 裸模板我就不说了,各个博客讲解的很明白 void insert(string s){ ,len=s.size(); ...
- 大数据之路day04_1--数组 and for循环进阶
Java数组 在开始之前,提一个十分重要的一点:注意:在给数组分配内存空间时,必须指定数组能够存储的元素来确定数组大小.创建数组之后不能修改数组的大小,可以使用length属性获取数组的大小.在jav ...
- Salesforce学习之路-developer篇(五)Aura组件原理及常用属性
很喜欢曾经看到的一句话:以输出倒逼输入.以输出的形式强制自己学习,确实是高效的学习方式,真的很棒.以下仅为个人学习理解,如有错误,欢迎指出,共同学习. 1. 什么是Lightning Componen ...
- 构建大型 Vue.js 项目的10条建议
下面是我在开发大型 Vue 项目时的最佳实践.这些技巧将帮助你开发更高效.更易于维护和共享的代码. 今年做自由职业的时候,我有机会开发了一些大型 Vue 应用程序.我所说的这些项目,Vuex stor ...
- 深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍
第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9905345.html 机器级代码 计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节. ...
- VLAN实验(4)单臂路由
1.选择1台Router路由器.2台S3700交换机和4台pc机,并根据实验编址完成此拓扑图. 2.对交换机mengyu-S2建立VLAN (1)建立两个VLAN,VLAN10和VLAN20,并添加描 ...
- VLAN实验(1)Access接口
1.选择两台S3700的交换机,5台PC机,并按照下图链接好并填写IP,完成此拓扑图 2.由于现在我们还没有划分VLAN,这5台PC,还在同一个VLAN中,现在我们启动所有的设备,这是所有的主机应该是 ...