java中的ThreadLocal-learning
为什么需要ThreadLocal
多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。
而线程安全是指
当多个线程访问某个方法时,不管你通过怎样的调用方式或者说这些线程如何交替的执行,我们在主程序中不需要去做任何的同步,
这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类时线程安全的。
或者:
不同的线程可以访问相同的资源,而不会暴露出错误的行为或产生不可预知的结果。
下面是线程不安全,相互影响:
public class UsuallyThreadTest {
static String localName = null;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
public void run() {
localName ="quan";
System.out.println(localName+" "+Thread.currentThread().getName());
localName = null;
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
System.out.println(localName+" after set localName= null "+Thread.currentThread().getName());
}
});
System.getenv();
// System.getProperty()
thread1.start();
thread2.start();
}
/**
* quan Thread-0
* quan after set localName= null Thread-1
*
* 线程1的修改对线程2产生影响,不安全。
*/
}
ThreadLocal是什么
它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,
在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。
ThreadLocal例子
public class LearningforThreadlocal {
static ThreadLocal<String> localName = new ThreadLocal<String>();
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
public void run() {
localName.set("quan");
System.out.println(localName.get());
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
System.out.println(localName.get()+"--->"+"after thread1 ,noremove");
localName.set("zhi");
System.out.println(localName.get());
localName.remove();
System.out.println("remove......::"+localName.get()+" in "+Thread.currentThread().getName());
}
});
// Thread thread3 = new Thread(new Runnable() {
// public void run() {
// System.out.println("no use set "+localName.get()+" in "+Thread.currentThread().getName());
// }
// });
Thread thread3 = new Thread(()->{
System.out.println("no use set "+localName.get()+" in "+Thread.currentThread().getName());
});
thread1.start();
thread2.start();
thread3.start();
}
}
/**
* re:
* quan
* no use set null in Thread-2
* null--->after thread1 ,noremove
* zhi
* remove......::null in Thread-1
*/
从上面可以看出,其实两个线程是不会相互影响的!!!!
ThreadLocal解析
set方法解析
/**
* set方法解析:
* public void set(T value) {
* Thread t = Thread.currentThread();//获取当前线程
* ThreadLocalMap map = getMap(t);//getMap方法如下面所示
* if (map != null)//如果不为空直接将当前线程中的threadLocals设置为键为当前ThreadLocal的引用,值为value
* map.set(this, value);
* else
* createMap(t, value);//否则创建threadLocals并设置键值对,createMap如下:
* }
*
* ThreadLocalMap getMap(Thread t) {
* return t.threadLocals;//返回当前线程中的变量threadLocals,第一次使用set方法是为null
* }
*
* void createMap(Thread t, T firstValue) {
* t.threadLocals = new ThreadLocalMap(this, firstValue);这里的createMap不仅建立了threadLocals,而且还设置了值
* }
*/
Get方法解析
/**
* get() 解析:
* public T get() {
* Thread t = Thread.currentThread();获取当前线程
* ThreadLocalMap map = getMap(t); 获取当前线ThreadLocals集合
* if (map != null) {
* ThreadLocalMap.Entry e = map.getEntry(this);
* //不为空直接获取集合中的值,this指的是哪个 ThreadLocal(例子localName)调用的引用
* if (e != null) {
* @SuppressWarnings("unchecked")
* T result = (T)e.value;获取ThreadLocal(例子localName)对应的值
* return result;
* }
* }
* return setInitialValue();
* }
*
* private T setInitialValue() {
* T value = initialValue();//内部方法,返回null
* Thread t = Thread.currentThread();
* ThreadLocalMap map = getMap(t);
* if (map != null)
* map.set(this, value);
* else
* createMap(t, value);
* return value;返回null
* }
*
*/
ThreadLocal和Thread的关系
/**
* 进入Thread内部可以知道有两个属性:
* ThreadLocal.ThreadLocalMap threadLocals = null;
* ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
* 由前缀知道都是ThreadLocal内部类ThreadLocalMap类型的变量
*
* ThreadLocal类型的本地变量是存放在具体的线程空间上,set方法将value添加到调用线程的threadLocals中,
* 当调用线程调用get方法时候能够从它的threadLocals中取出变量。
* 线程不断,变量就一直在threadlocals中,所以不用的时候使用remove
*

ThreadLocal无继承性
例子说明:
/**
* ThreadLocal不具有继承性
*/
public class ThreadLocalInherit {
static ThreadLocal<String> localName = new ThreadLocal<String>(); public static void main(String[] args) {
localName.set("DONE");//在main线程里面设置了localName的值
System.out.println(Thread.currentThread().getName()+"使用了:localName.set(\"DONE\")"); Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("子类"+localName.get());
}//子类去获取的时候
}); thread.start();
}
/**
* re:
* main使用了:localName.set("DONE")
* 子类null
*/ }
注意:InheritableThreadLocal类继承了ThreadLocal,扩展了ThreadLocal。实现了可以继承的关系
ThreadLocalMap与内存泄漏
/**
* 解析一下ThreadLocals的类型ThreadLocalMap
* 实际上是一个:private Entry[] table;
* Entry[] 是:
*
* static class Entry extends WeakReference<ThreadLocal<?>> {
* Object value;
* Entry(ThreadLocal<?> k, Object v) {构造函数,ThreadLocal的引用k被传进WeakReference的构造函数。
* super(k);
* value = v;
* }
* }
*---》所以ThreadLocalMap的key就是对ThreadLocal的弱引用
*
* 如果没有执行remove,有可能造成内存泄漏
*
* key弱引用在gc的时候没有其他强依赖,就会被gc掉。但是value不会。
* 可能会出现key为null,但是value还存在的情况。
* 所以我们使用后一定要用remove掉
*/
ThreadLocal只是一个工具类,他为用户提供get、set、remove接口操作实际存放本地变量的threadLocals(调用线程的成员变量),
threadLocals是一个ThreadLocalMap类型的变量,
java中的ThreadLocal-learning的更多相关文章
- Java中的ThreadLocal深入理解
提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和 ...
- 理解Java中的ThreadLocal
提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和 ...
- Java中的ThreadLocal详解
一.ThreadLocal简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线 ...
- 谈谈Java中的ThreadLocal
什么是ThreadLocal ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本.通过ThreadLocal可以将对象的 ...
- 理解java中的ThreadLocal(转)
一.对ThreadLocal概述 JDK API 写道: 该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的 ...
- 理解java中的ThreadLocal 专题
ThreadLocal每一印象: public class IncrementWithStaticVariable{ private static int seqNum = 0; public int ...
- Java中的ThreadLocal
关于 ThreadLocal,我们经常用它来解决多线程并发问题,那它究竟是如何做到的?今天就让我们来好好看一下. 从源码入手 首先,让我们看看 ThreadLocal 类中的介绍: This clas ...
- java 中的 ThreadLocal
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...
- Java中的ThreadLocal使用
ThreadLocal用于下面的场景: 1. 不允许多个线程同时访问的资源 2. 单个线程存活过程只使用一个实例 官方定义如下: This class provides thread-local va ...
- Java ThreadLocal Example(java中的ThreadLocal例子)
Java ThreadLocal is used to create thread local variables. We know that all threads of an Object sha ...
随机推荐
- prometheus监控java项目(jvm等):k8s外、k8s内
前言 虽然可以使用jvisualvm之类的工具监控java项目,但是集群环境下,还是捉襟见肘,下面介绍如何用主流的prometheus来监控java项目. java项目配置 在pom.xml中添加依赖 ...
- 【C# 线程】线程池 epoll和IOCP之比较
总结:IOCP :我的打印文件放在店里面排队,轮到我打印了,店长帮我打印一下,打印好了通知我来拿 Epoll :我的打印文件放在店里面排队,轮到我叫我一下,我自己来打印. 直入正题:Epoll 是L ...
- 【基础知识】CPU 是如何工作的 |CPU 通过总线读取内存的工作方式
一.简单cpu 是如何工作 方式讲解 CPU 的根本任务就是执行指令,对计算机来说最终都是一串由 0 和 1 组成的序列.CPU 从逻辑上可以划分成 3 个模块,分别是控制单元.运算单元和存储单元 ...
- Qt:QUrl
1.说明 概述 一个代表URL的类,此外还支持国际域名(IDNs). 通常在初始化时传入QString构造QUrl,除此之外还能用setUrl(). URL有两种表示格式:编码.未编码.未编码URL常 ...
- Python字典的创建与复制
Python 字典练习题 1.字典的创建 1.1 普通创建 d={'name':'Allen','age':21,'gender':'male'} print(d) # {'name': 'Allen ...
- SpringBoot入门二:与Mybatis整合
一.编程步骤 1.引入依赖 springboot相关依赖(略).mybatis-spring-boot-starter.mysql.druid.lombook <dependency> & ...
- 微服务从代码到k8s部署应有尽有系列(十三、服务监控)
我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...
- VS Code远程链接报错Could not establish connection to “hz.matpool.com”
VS Code远程链接报错Could not establish connection to "hz-t2.matpool.com" 输出的部分内容 安装Git git for w ...
- swoole 聊天室
1:宝塔终端安装php 2:宝塔终端检测是否安装好 php-v 3:宝塔面板安装swoole扩展,终端检测 php -m 查看扩展 扩展已经安装完毕
- 一比一还原axios源码(二)—— 请求响应处理
上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...