• ThreadLocal


    1,ThreadLocal是什么:

    ThreadLocal也是解决多线程访问共享变量问题的,不同于加锁,他会在每一个线程内部创建副本,

    每个线程独立访问自己内部的副本,不会产生冲突。

     

    2,用法:

    示例:

      public class ThreadLocalTest {
      
          static ThreadLocal<String> localVar = new ThreadLocal<>();
      
          static void print(String str) {
              //打印当前线程中本地内存中本地变量的值
              System.out.println(str + " :" + localVar.get());
             //清除本地内存中的本地变量
             localVar.remove();
         }
     
         public static void main(String[] args) {
             Thread t1  = new Thread(new Runnable() {
                @Override
                 public void run() {
                     //设置线程1中本地变量的值
                     localVar.set("localVar1");
                     //调用打印方法
                     print("thread1");
                     //打印本地变量
                     System.out.println("after remove : " + localVar.get());
                 }
             });
     
             Thread t2  = new Thread(new Runnable() {
                 @Override
                 public void run() {
                     //设置线程1中本地变量的值
                     localVar.set("localVar2");
                     //调用打印方法
                     print("thread2");
                     //打印本地变量
                     System.out.println("after remove : " + localVar.get());
                 }
             });
     
            t1.start();
             t2.start();
         }
    }
    View Code

    3,原理:

    ThreadLocal类:

    ①内部类:ThreadLocalMap

    是一个哈希表,循环数组+开发地址法中线性探测法解决哈希冲突。

    什么意思呢?试试想一下:线性探测法会在数组中形成以null隔开的若干‘块’,我们把它类比成拉链法里面的每一个链表。

    线性探测法在一个快中(快可能未null)添加元素就相当于尾插法,删除元素,就要调整该快中,被删除元素之后的元素,要前移

    保证他们下次能被探测到。就绪拉链法里面的调整指针关系。

    Entry数组储存的是key-value键值对,key是ThreadLocal,value是Object对象。

    • 参数:

    • 方法:主要是哈希表的,增删改查

    ①增删改查之前,首先要介绍一下expungeStaleEntry()函数,顾名思义删除元素用的

    ②getEntry():

    getEntryAfterMiss():

    ③set()函数:

    replaceStaleEntry()

     

    cleanSomeSlots();

     ④remove()

     ⑤rehash()

     expungeStaleEntries()

     

     resize()扩容:

    总结:ThreadLocalMap(),哈希表,数组+线性探测法解决哈希冲突。初始容量16,扩容*2.

    在增删改查中不停清理,失效的TreadLocal元素。

    内存泄漏问题:

    <1>ThreadLocalMap的Entry数组是key为ThreadLocal的弱引用,而valve是强引用。如果ThreadLocal对象没有被外部强引用,垃圾回收时,key被回收

    为null但是value还在。造成内存泄漏。

    <2>虽然ThreadLocalMap在get(),set()函数里多次清理key为null的失效元素,但是当没有调用get(),set()时,不会清理。

     

    解决方法:<1>使用完ThreadLocal后手动调用remove方法。

    <2>将ThreadLocal定义为private static 随线程一起消亡。

     

    ②看完ThreadLocalMap,在回到ThreadLocal类,

    • set()

     

    • get()

     map空就初始化map

    • 虽然ThreadLocalMap是ThreadLocal内部类,但ThreadLocal里并没有ThreadLocalMap参数,

    而是通过getMap()方法;获得线程的threadlocalS。

                                   调用getMap的地方也是传入当前线程的

     

                    进入Thread类:

    ThreadLocalMap实例化在Thread类里作为参数。即每一个线程有一个,哈西表,threadlocals,顾名思义用来存放该

    线程ThreadLocals变量的。

    ThreadLocal是ThreadLocalMap的封装,提供了set(),get();看起来是每个Threadlocal变量单独get(),set()。背后还是通过每个Thred的

    ThredLocalMap统一管理所有ThreadLocal变量;

     参考:

    https://www.cnblogs.com/fsmly/p/11020641.html

    https://baijiahao.baidu.com/s?id=1653790035315010634&wfr=spider&for=pc

    https://www.jianshu.com/p/80866ca6c424

    https://blog.csdn.net/ywlmsm1224811/article/details/91388109

  • 相关阅读:
    Entity Framework 第十篇 条件查询
    Entity Framework 第九篇 关于自增列的事务处理
    Entity Framework 第八篇 结构优化
    Entity Framework 第七篇 简化排序
    控件截图Cache
    Java基础_自加运算
    Java基础_赋值运算
    Java基础_字符与字符串的运算
    同步和异步
    Application中的name属性
  • 原文地址:https://www.cnblogs.com/wangpan8721/p/13800599.html
Copyright © 2020-2023  润新知