阿里+++

ThreadLocal

    线程变量存放在当前线程变量中,线程上下文中,set将变量添加到threadLocals变量中

     Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThreadLocals用来存储当前操作的ThreadLocal的引用及变量对象,把当前线程的变量和其他的线程的变量之间进行隔离,从而实现了线程的安全性

        InheritableThreadLocal类重写get/set方法会对线程的inheritableThreadLocals变量初始化,在对子线程初始化时将子线程的inheritableThreadLocals变量赋值为父线程的inheritableThreadLocals变量值,实现了子线程继承父线程

内存泄漏问题

       Thread->ThreadLocalMap->Entry->value,ThreadLocalMap是继承了WeakReference的entry集合,但是线程一直没有remove,threadLocal下次GC将弱引用对象回收,entry对象的key为null,value值却是强引用关系

      ThreadLocal每次调用get、set、remove的时候都会直接或者间接的调用expungeStaleEntry方法清除掉key为null的Entry;

   主线程执行ThreadLocal.remove()后,子线程中的ThreadLocal并不会被remove()判空,导致线程池中维护的ThreadLocal存储的值一直不变

池化:InheritableThreadLocal子线程使用线程池 更改存储 变量值不变

 没找到对应的InheritableThreadLocal 自然改不了:普通的ThreadLocal会让子线程获取不到get值

  池化:减少资源对象创建次数

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals) {
    //省略部分代码
   
    //如果父线程inheritableThreadLocals不为空,则保存下来
    if (inheritThreadLocals && parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    
    //省略部分代码
}

注意 使用静态和不使用静态时候

  使用静态的InheritableThreadLocal 线程池复用时候不会有问题

  ThreadLocal是线程本地变量,每个线程有自己的副本;InheritableThreadLocal具有继承性,在创建子线程时,子线程可以继承父线程的变量副本。

https://www.cnblogs.com/shanheyongmu/p/17922183.html   

https://www.cnblogs.com/tiancai/p/17622821.html       InheritableThreadLocal详解 - 简书
 

TransmittableThreadLocal

继承自InheritableThreadLocal,在线程池中传递ThreadLocal变量的值

GitHub - alibaba/transmittable-thread-local: 📌 a missing Java std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.

/*
* holder里面存储所有关于TransmittableThreadLocal的引用
*/
public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> implements TtlCopier<T> {

  // 1. 此处的holder是他的主要设计点,后续在构建TtlRunnable
  private static InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>> holder =
            new InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>>() {
                @Override
                protected WeakHashMap<TransmittableThreadLocal<Object>, ?> initialValue() {
                    return new WeakHashMap<TransmittableThreadLocal<Object>, Object>();
                }

                @Override
                protected WeakHashMap<TransmittableThreadLocal<Object>, ?> childValue(WeakHashMap<TransmittableThreadLocal<Object>, ?> parentValue) {
                    return new WeakHashMap<TransmittableThreadLocal<Object>, Object>(parentValue);
                }
            };

    @SuppressWarnings("unchecked")
    private void addThisToHolder() {
        if (!holder.get().containsKey(this)) {
            holder.get().put((TransmittableThreadLocal<Object>) this, null); // WeakHashMap supports null value.
        }
    }

  @Override
    public final T get() {
        T value = super.get();
        if (disableIgnoreNullValueSemantics || null != value) addThisToHolder();
        return value;
    }
    /**
     * see {@link InheritableThreadLocal#set}
     */
    @Override
    public final void set(T value) {
        if (!disableIgnoreNullValueSemantics && null == value) {
            // may set null to remove value
            remove();
        } else {
            super.set(value);
            addThisToHolder();
        }
    }
    /**
     * see {@link InheritableThreadLocal#remove()}
     */
    @Override
    public final void remove() {
        removeThisFromHolder();
        super.remove();
    }

    private void superRemove() {
        super.remove();
    }
}

1.继承InheritableThreadLocal,成立个TransmittableThreadLocal类, 该类中有一个hodel变量维护所有的TransmittableThreadLocal引用。

2.在实际submit任务到线程池的时候,需要调用TtlRunnable.get,构建一个任务的包装类。使用装饰者模式,对runnable线程对象进行包装,在初始化这个包装对象的时候,获取主线程里面所有的TransmittableThreadLocal引用,以及里面所有的值,这个值是当前父线程里面的(跟你当时创建这个线程的父线程没有任何关系,注意,这里讲的是线程池的场景)。

3.对数据做规整,根据收集到的captured (这个对象里面存储的都是主线程里面能够获取到TransmittableThreadLocal以及对应的值) 做规整,去掉当前线程里面不需要的,同时将剩余的key和value ,更新到当前线程的ThreadLocal里面。这样就达到了在池化技术里面父子线程传值的安全性

多线程篇-TransmittableThreadLocal解决池化复用线程的传值问题 - 知乎

hashMap1.7与1.8

1.7底层是entry数组+链表

颠倒链表顺序 元素插入前是否需要扩容,扩容后all元素重新计算下位置

头插法:逆序 环形链表死循环

ReentrantLock+Segment+HashEntry

   第一次put hash(key)定位segment 未初始化cas赋值

   第二次put,hashEntry ReentrantLock.tryLock获取锁,否自旋tryLock 获取锁 超次挂起

1.8node数组+链表+红黑树

保持原链表顺序 元素插入后检查是否扩容

链表长度达到8/元素总数达到64

synchronized+CAS+HashEntry+红黑树

   没有初始化initTable

   没有hash冲突 cas插入,否 加锁

      链表遍历到尾部插入 ,红黑树就是红黑树的结构插入

   添加成功addCount统计size是否需要扩容

 高低位指针的形式,将低位上的数据移动到原来的位置,高位上的数据移动到【原来的位置+旧数组容量】的位置,避免了rehash

AQS

ConditionObject的await和signal等同Object的wait、notify函数(Synchronized)

五层 

    如果被请求的共享资源空闲,将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;

    如果共享资源被占用,需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列(Craig、Landin and Hagersten,是单向链表)的变体实现的,将暂时获取不到锁的线程加入到队列中(AQS是通过将每条请求共享资源的线程封装成一个节点node来实现锁的分配)

理解AQS的原理及应用总结_aqs原理-CSDN博客 这篇阿里P6+的水平了

CountDownLatch和CyclicBarrier

CountDownLatch放行由其他线程控制,一直等待直到线程完成操作

   计数器 aqs,countDown减state-1,await 判断state==0 非加入队列阻塞 头节点自旋等待state=0

CyclicBarrier本身控制,线程到达状态 暂停等待其他线程,all线程到达后 继续执行

    任务线程调用,线程相互等待,可重用

    ReentrantLock加上Condition,await,count -1 ReentrantLock线程安全性,如count不为0,加则condition队列中,如count==0,把节点从condition队列添加至AQS的队列中进行全部唤醒,并且将parties的值重新赋值为count的值(实现复用)

相关推荐

  1. <span style='color:red;'>阿里</span>+++

    阿里+++

    2024-04-07 15:44:02      34 阅读
  2. 阿里云docker加速

    2024-04-07 15:44:02       52 阅读
  3. 阿里云安装docker

    2024-04-07 15:44:02       62 阅读
  4. 阿里控股 面经

    2024-04-07 15:44:02       61 阅读
  5. 阿里云云数据库RDS

    2024-04-07 15:44:02       48 阅读
  6. 阿里云OCR识别

    2024-04-07 15:44:02       44 阅读
  7. 阿里云入门

    2024-04-07 15:44:02       57 阅读
  8. 阿里 EasyExcel 表头国际化

    2024-04-07 15:44:02       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-07 15:44:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-07 15:44:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-07 15:44:02       82 阅读
  4. Python语言-面向对象

    2024-04-07 15:44:02       91 阅读

热门阅读

  1. SpringBoot学习笔记

    2024-04-07 15:44:02       33 阅读
  2. Qt文本搜索

    2024-04-07 15:44:02       34 阅读
  3. 如何设置redis集群

    2024-04-07 15:44:02       35 阅读
  4. 前端面试经验

    2024-04-07 15:44:02       40 阅读
  5. 训练营十四天(二叉树的遍历)

    2024-04-07 15:44:02       142 阅读
  6. 1688详情、搜索、店铺、图搜

    2024-04-07 15:44:02       39 阅读
  7. day19-归并两个有序数组

    2024-04-07 15:44:02       38 阅读
  8. Python基础

    2024-04-07 15:44:02       37 阅读
  9. 加密算法(二)

    2024-04-07 15:44:02       34 阅读
  10. Linux——基础命令

    2024-04-07 15:44:02       41 阅读