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 ...
随机推荐
- 用这个BI工具,不会代码的业务人员也能做数据分析!
随着企业的迅速发展,企业对数据分析的需求也在不断地凸显,但我们在实际的工作中经常会遇到这样尴尬的情形:擅长数据分析的人不懂业务,擅长业务的人又不了解数据分析.那么怎么让更懂业务逻辑.业务分析需求和痛点 ...
- python基础之数值类型与序列类型
Hello大家好,我是python学习者小杨同学,已经学习python有一段时间,今天将之前学习过的内容整理一番,在这与大家分享与交流,现在开始我们的python基础知识之旅吧. 数值类型与序列类型 ...
- Oracle之单行函数(字符串函数/数字函数/转换函数/日期函数/通用函数)
虚拟表DUAL介绍: dual是一张虚拟表,只有一行一列,用来构成select的语法规则. Oracle的查询中,必须使用"select 列- from 表"的完整语法,当查询单行 ...
- idea教程--如何申请免费的ideaIDE
开始申请前请先到 https://www.jetbrains.com/zh/student/ 阅读免费学生授权的介绍和常见问题,再依照下方流程进行申请. (1)到 https://www.jetbra ...
- Chrome:开发者模式下复制Element下的代码
Element模块下的代码只能一行一行复制,想要复制一个代码块,可以把该代码块先收起来,再对这个收起来的代码块进行复制就OK了
- Python:numpy
学习自:NumPy 教程 | 菜鸟教程 官网:Numpy官方文档 1.简介 numpy主要用于数组计算,包含: 1)一个强大的N维数组对象ndarray 2)广播功能函数 3)整合 C/C++/For ...
- 革命性创新,动画杀手锏 @scroll-timeline
在 CSS 规范 Scroll-linked Animations 中,推出了一个划时代的 CSS 功能.也就是 -- The @scroll-timeline at-rule,直译过来就是滚动时间线 ...
- 详细了解 synchronized 锁升级过程
前言 首先,synchronized 是什么?我们需要明确的给个定义--同步锁,没错,它就是把锁. 可以用来干嘛?锁,当然当然是用于线程间的同步,以及保护临界区内的资源.我们知道,锁是个非常笼统的概念 ...
- Hadoop原生对象存储Ozone
Hadoop 社区推出了新一代分布式Key-value对象存储系统 Ozone,同时提供对象和文件访问的接口,从构架上解决了长久以来困扰HDFS的小文件问题.本文作为Ozone系列文章的第一篇,抛个砖 ...
- go RWMutex 的实现
Overview go 里面的 rwlock 是 write preferred 的,可以避免写锁饥饿. 读锁和写锁按照先来后到的规则持有锁,一旦有协程持有了写锁,后面的协程只能在写锁被释放后才能得到 ...