为什么需要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的更多相关文章

  1. Java中的ThreadLocal深入理解

    提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和 ...

  2. 理解Java中的ThreadLocal

    提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和 ...

  3. Java中的ThreadLocal详解

    一.ThreadLocal简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线 ...

  4. 谈谈Java中的ThreadLocal

    什么是ThreadLocal ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本.通过ThreadLocal可以将对象的 ...

  5. 理解java中的ThreadLocal(转)

    一.对ThreadLocal概述 JDK API 写道: 该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的 ...

  6. 理解java中的ThreadLocal 专题

    ThreadLocal每一印象: public class IncrementWithStaticVariable{ private static int seqNum = 0; public int ...

  7. Java中的ThreadLocal

    关于 ThreadLocal,我们经常用它来解决多线程并发问题,那它究竟是如何做到的?今天就让我们来好好看一下. 从源码入手 首先,让我们看看 ThreadLocal 类中的介绍: This clas ...

  8. java 中的 ThreadLocal

    首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...

  9. Java中的ThreadLocal使用

    ThreadLocal用于下面的场景: 1. 不允许多个线程同时访问的资源 2. 单个线程存活过程只使用一个实例 官方定义如下: This class provides thread-local va ...

  10. Java ThreadLocal Example(java中的ThreadLocal例子)

    Java ThreadLocal is used to create thread local variables. We know that all threads of an Object sha ...

随机推荐

  1. unittest测试框架,HTMLTestReportCN模块生成的测试报告中展示用例说明的配置方法

    1.前言 想要生成的html测试报告中展示每个测试用例的说明信息,方便了解测试案例的测试点或者其他信息,目前知道的有2种 2.方法介绍 * 方法1: 要添加说明的测试用例,将说明信息用3个引号包裹起来 ...

  2. golang线程安全

    目录 1.golang的map是线程安全的吗?怎么安全使用map 2.线程独享什么,共享什么 3.进程状态转换 4.Log包线程安全吗? 5.写的循环队列是不是线程安全? 6.go协程线程安全吗 7. ...

  3. RESTful风格了解

    最近在学习springboot,一直听到一个词叫RESTful风格,今天找了一下书了解了一番.spring mvc除了支持json数据交互外,还支持RESTful风格 RESTful也称为REST(r ...

  4. Typora下载及MarkDown语法详解

    写博客的重要性 作为一名程序员,写博客已经成了一项基本技能和素养.为什么要写博客?因为它能将我们学习的知识总结起来,提高我们对知识的深层次理解,还能将我们所学知识记录下来,以便于以后回忆.要想写博客, ...

  5. AHUACM寒假集训I(基础数据结构+串串)

    H.超级钢琴 luoguP2048 题目大意: 求出一个长N序列中所有长度在L到R的子序列中序列和最大的K个,并求这K个的和 思路: 暴力的话可以求出所有满足要求的子序列然后排序,然后显然会T. 所以 ...

  6. tomcat启动错误:Error running 'Tomcat 9.0.34': Address localhost:1099 is already in use

    解决方法博客地址:https://blog.csdn.net/weixin_46697202/article/details/105782670

  7. CNN(卷积神经网络)入门

    参考博文: 深度学习基础--卷积--1*1的卷积核与全连接的区别:https://blog.csdn.net/wydbyxr/article/details/84061410 如何理解卷积神经网络中的 ...

  8. (八)使用 jmh 压测 Dubbo

    1.JMH简介 JMH即Java Microbenchmark Harness,是Java用来做基准测试的一个工具,该工具由OpenJDK提供并维护,测试结果可信度高. 相对于 Jmeter.ab , ...

  9. Mock平台2-Java Spring Boot框架基础知识

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 认识Spring Boot 在N年前的大学时代想要开发一个Web服务使用的还是SSH框架(struts+spring+hibernate) ...

  10. linux作业--第二周

    1.显示/etc目录下,以非字母开头,后面跟了一个字母以及其它任意长度任意字符的文件或目录 ls /etc/ | grep ^[^[:alpha:]][[:alpha:]].* 2.复制/etc目录下 ...