ThreadLocal

  • 多个线程访问同一个共享变量时特别容易出现并发问题,特别是多线程需要对共享变量进行写入时。为了保证线程安全,一般使用者在访问共享变量的时候需要进行适当的同步,如图

  • 同步的一般措施是加锁,这就需要使用者对锁有一定的了解,这显然加重了使用者的负担,那么有没有一种方法可以做到,当创建一个变量后,每个线程对其进行访问的时候访问的是自己线程的变量呢?其实ThreadLocal就可以做到。

  • ThreadLocal是JDK包提供的,它提供了线程本地变量,也就是说如果创建了一个ThreadLocal变量,那么访问这个变量的每一个线程都会有这个变量的一个本地副本。当多线程操作这个变量的时候,实际操作的就是自己本地内存的里面的里面的变量,从而避免了线程安全问题。创建一个ThreadLocal变量后,每一个线程都会复制一个变量到自己的本地内存。

  • ThreadLocal使用实例

    package com.heiye.learn1;
    
    public class ThreadLocalTest {
    //print方法
    static void print(String threadName) {
    //打印当前线程本地内存中LocalVariable变量的值
    System.out.println(threadName + ":" + localVariable.get());
    //清除当前线程本地内存中的localVariable变量值
    //localVariable.remove();
    } //创建ThreadLocal变量
    static ThreadLocal<String> localVariable = new ThreadLocal<>(); public static void main(String[] args) {
    //创建线程threadOne
    Thread threadOne = new Thread(new Runnable() {
    @Override
    public void run() {
    //设置线程one变量localVariable值
    localVariable.set("threadOne local Variable");
    //调用打印函数
    print("threadOne");
    //打印本地变量值
    System.out.println("threadOne remove after" + ":" + localVariable.get());
    }
    });
    //创建线程threadTwo
    Thread threadTwo = new Thread(new Runnable() {
    @Override
    public void run() {
    //设置线程two变量localVariable值
    localVariable.set("threadTwo local Variable");
    //调用打印函数
    print("threadTwo");
    //打印本地变量值
    System.out.println("threadTwo remove after" + ":" + localVariable.get());
    }
    }); threadOne.start();
    threadTwo.start();
    }
    }
    • 线程one首先通过set()方法为threadLocal变量设置了一个值,这其实设置的就是线程one本地内存中对于threadLocal变量的一个副本。这个副本是线程two访问不了的。
  • 如果清除当前线程本地内存中的localVariable变量值,也就是执行localVariable.remove();则:

ThreadLocal实现原理

  • 首先查看一下ThreadLocal类图结构

  • 由该图可知,Thread类有一个ThreadLocals和inheritableThreadLocals,它们都是ThreadLocalMap类型的变量,而ThreadLocalMap是一个定制化的HashMap。在默认的情况下,每个线程中的两个变量都为null,只有当第一个线程调用ThreadLocal的set或者get方法时才会创建它们,其实每个线程得到本地变量不是存放在ThreadLocal实例里面,而是存放在具体的线程内存空间里。ThreadLocal就是一个工具壳,它通过set方法把value值存放在调用线程的threadlocals里面并存放起来,当调用线程调用它的get()方法的时候,再从当前线程的threadLocals变量里面将其拿出来使用。

  • 分析set,get,remove逻辑

       //set
    public void set(T value) {
    //获取当前线程
    Thread t = Thread.currentThread();
    //将当前线程作为key,到ThreadLocalMap取查找对应的线程变量
    ThreadLocalMap map = getMap(t);
    //如果找到,则设置
    if (map != null)
    map.set(this, value);
    else //第一次调用就创建当前线程所在的hashmap
    createMap(t, value);
    } //get
    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();
    } //remove
    public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
    m.remove(this);
    }
  • 在每一个线程内都有一个名为threadLocals的成员变量,该变量的类型为HashMap,其中的key为我们定义的threadLocal变量的this引用,value为我们使用set方法设置的值。每个线程的本地变量存放在自己的内存变量ThreadLocals中,如果当前线程一直不消亡,那么这些本地变量会一直存在,所有可能造成内存溢出。

9-threadLocal的更多相关文章

  1. ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...

  2. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  3. Threadlocal使用Case

    Threadlocal能够为每个线程分配一份单独的副本,使的线程与线程之间能够独立的访问各自副本.Threadlocal 内部维护一个Map,key为线程的名字,value为对应操作的副本. /** ...

  4. 多线程映射工具——ThreadLocal

    ThreadLocal相当于一个Map<Thread, T>,各线程使用自己的线程对象Thread.currentThread()作为键存取数据,但ThreadLocal实际上是一个包装了 ...

  5. ThreadLocal 工作原理、部分源码分析

    1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...

  6. ThreadLocal<T>的是否有设计问题

    一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...

  7. 理解ThreadLocal —— 一个map的key

    作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...

  8. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  9. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  10. ThreadLocal 源码剖析

    ThreadLocal是Java语言提供的用于支持线程局部变量的类.所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量(每个线程一个拷贝).在各个Java web的各种框架 ...

随机推荐

  1. Linux命令全训练

    一.实验目的 为后续上机实验做准备,熟悉常用的Linux操作. 二.实验平台 操作系统:Ubuntu14.04 三.实验内容和要求 1.Linux系统中的常用快捷键 Tab 自动补全 上下箭头 显示历 ...

  2. ubuntu黑屏无法进入系统【Recovery Mode急救】

    一.问题 前言:因为一次美化配置ubuntu导致系统启动黑屏,无法进入系统.之前并没有系统备份,后果严重还好修复了,记录下修复步骤备用.  事件:就是因为修改了 /usr/share/gnome-sh ...

  3. Java异常与异常处理

    异常体系结构 1.所有异常都继承于Throwable类,其下有两大子类: (1)Error类:错误,一般编程人员不太接触,如虚拟机错误.线程死锁.硬伤:使程序崩溃 (2)Exception类:异常,编 ...

  4. 基于SigalR实现的奥运会实时金牌榜

    系统架构 三端 winform 后台数据管理 + Asp.Net Mvc 前台数据展示 + Xamarin.Forms 移动端跨平台APP 因为本人的代码水平一般,期间遇到了一些问题,如signalR ...

  5. 根据短链生成二维码并上传七牛云(Java)

    通过短链生成二维码并上传七牛云(Java) 前言 网上这种帖子其实也是很多,大部分搜出来的是CSDN的,然后点进去一看都几乎一样:所以这次给个自己实践的例子记录. 这次也是通过搜索得到的一部分能实现这 ...

  6. Struts2 的 OGNL

    ONGL简介: OGNL 的全称是对象图导航语言( Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存 ...

  7. 一文看懂String类中的常用方法

    1.int length(): 返回字符串的长度: return value.length 2.char charAt(int index): 返回某索引处的字符return value[index] ...

  8. 洛谷P1583——魔法照片(结构体排序)

    https://www.luogu.org/problem/show?pid=1583#sub 题目描述 一共有n(n≤20000)个人(以1--n编号)向佳佳要照片,而佳佳只能把照片给其中的k个人. ...

  9. symfony2中mysql和mongodb的增删改查总结

    https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manip ...

  10. 教你用ps如何将图片、文字做出模糊斑驳的作旧效果

    1.对图片的图层执行滤镜-风格化-扩散,选变亮优先. 2.选择画笔工具,在画笔选项里选择喷溅59像素,画笔大小我用的是100px,大家可以根据自己的情况自定义大小,前景设置为黑色. 3.在图章图层上方 ...