首页 > 编程语言 >Netty源码-02-FastThreadLocalThread

Netty源码-02-FastThreadLocalThread

时间:2022-11-16 22:22:07浏览次数:56  
标签:02 Netty Object return index threadLocalMap InternalThreadLocalMap 源码 get

一 Demo

public class FastThreadLocalTest00 {

    private final static FastThreadLocal<Long> v = new FastThreadLocal<Long>() {
        @Override
        protected Long initialValue() throws Exception {
            System.out.println("init");
            return 0L;
        }
    };

    public static void main(String[] args) throws InterruptedException {
        new FastThreadLocalThread(() -> {
            System.out.println("fast1 v1=" + v.get());
            v.set(1L);
            System.out.println("fast1 v2=" + v.get());
            v.remove();
            System.out.println("fast1 v3=" + v.get());
        }).start();

        new FastThreadLocalThread(() -> {
            System.out.println("fast2 v1=" + v.get());
            v.set(2L);
            System.out.println("fast2 v2=" + v.get());
            v.remove();
            System.out.println("fast2 v3=" + v.get());
        }).start();

        Thread.sleep(3_000);
    }
}

二 FastThreadLocal

// FastThreadLocal.java

private final int index; // 指向InternalThreadLocalMap中数组下一个可用脚标

public FastThreadLocal() {
        this.index = InternalThreadLocalMap.nextVariableIndex(); // index初始化时为默认值0 把0处的slot预留出来 从1开始可用 此时InternalThreadLocalMap里面的数组并没有实例化
    }
// InternalThreadLocalMap.java
public static int nextVariableIndex() {
        int index = nextIndex.getAndIncrement();
        if (index < 0) {
            nextIndex.decrementAndGet();
            throw new IllegalStateException("too many thread-local indexed variables");
        }
        return index;
    }

三 get

// FastThreadLocal.java
public final V get() {
        InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get(); // Netty自己封装的数据结构 不是直接用的Jdk原生的threadLocals指向的ThreadLocalMap 懒加载触发InternalThreadLocalMap中的数组初始化
        Object v = threadLocalMap.indexedVariable(this.index);
        if (v != InternalThreadLocalMap.UNSET) {
            return (V) v;
        }
        /**
         * 首次调用get没有数据的回调initialValue方法
         */
        return initialize(threadLocalMap);
    }

1 InternalThreadLocalMap懒加载

// InternalThreadLocalMap.java
public static InternalThreadLocalMap get() { // 懒加载 InternalThreadLocalMap使用数组存储元素 初始化默认长度32 全部用UNSET标识占位 脚标从1开始可用
        Thread thread = Thread.currentThread(); // Netty封装了FastThreadLocalThread 根据线程类型区分数据存储策略
        if (thread instanceof FastThreadLocalThread) { // 配套Netty封装的FastThreadLocalThread使用
            return fastGet((FastThreadLocalThread) thread);
        } else { // 配套Jdk的Thread使用
            return slowGet();
        }
    }

private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {
        InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();
        if (threadLocalMap == null) {
            thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap()); // 实例化InternalThreadLocalMap存储数据 默认长度32 全部用UNSET填充
        }
        return threadLocalMap;
    }

private InternalThreadLocalMap() {
        this.indexedVariables = newIndexedVariableTable(); // 初始化数组 默认容量32
    }

private static Object[] newIndexedVariableTable() {
        Object[] array = new Object[INDEXED_VARIABLE_TABLE_INITIAL_SIZE]; // 数组初始化 默认容量32
        Arrays.fill(array, UNSET); // 全部用UNSET标识填充
        return array;
    }

2 数组元素设值

// FastThreadLocal.java
 Object v = threadLocalMap.indexedVariable(this.index);
// InternalThreadLocalMap.java
public Object indexedVariable(int index) { // 根据数组脚标寻址
        Object[] lookup = indexedVariables;
        return index < lookup.length? lookup[index] : UNSET;
    }

3 首次get没值触发回调初始值

// FastThreadLocal.java
/**
         * 首次调用get没有数据的回调initialValue方法
         */
        return initialize(threadLocalMap);

private V initialize(InternalThreadLocalMap threadLocalMap) {
        V v = null;
        try {
            v = initialValue(); // 回调initialValue方法
        } catch (Exception e) {
            PlatformDependent.throwException(e);
        }

        threadLocalMap.setIndexedVariable(index, v); // 首次get无值时将initialValue方法的值放到数组
        addToVariablesToRemove(threadLocalMap, this);
        return v;
    }

四 set

// FastThreadLocal.java
public final void set(V value) {
        if (value != InternalThreadLocalMap.UNSET) { // 有效值
            InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get(); // 数据结构
            setKnownNotUnset(threadLocalMap, value);
        } else {
            remove();
        }
    }

private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {
        if (threadLocalMap.setIndexedVariable(index, value)) { // 向数组中放元素 脚标后移 容量不够触发数组扩容
            addToVariablesToRemove(threadLocalMap, this);
        }
    }
// InternalThreadLocalMap.java
public boolean setIndexedVariable(int index, Object value) {
        Object[] lookup = this.indexedVariables;
        if (index < lookup.length) {
            Object oldValue = lookup[index];
            lookup[index] = value;
            return oldValue == UNSET;
        } else {
            expandIndexedVariableTableAndSet(index, value); // 扩容
            return true;
        }
    }

五 remove

// FastThreadLocal.java
public final void remove() {
        remove(InternalThreadLocalMap.getIfSet());
    }

public final void remove(InternalThreadLocalMap threadLocalMap) {
        if (threadLocalMap == null) {
            return;
        }

        Object v = threadLocalMap.removeIndexedVariable(index);
        removeFromVariablesToRemove(threadLocalMap, this);

        if (v != InternalThreadLocalMap.UNSET) {
            try {
                onRemoval((V) v);
            } catch (Exception e) {
                PlatformDependent.throwException(e);
            }
        }
    }

标签:02,Netty,Object,return,index,threadLocalMap,InternalThreadLocalMap,源码,get
From: https://www.cnblogs.com/miss-u/p/16897727.html

相关文章

  • 第五章第6节: 2020.06.10 智能互联网之弹性容器云与Service Mesh【六】
                                                         ......
  • [AGC002F] Leftmost Ball
    好题题面:给你\(n\)种颜色的球,每种颜色的球有\(k\)个,把这\(n*k\)个球排成一排,把每一种颜色的最左边出现的球涂成白色(初始球不包含白色),求有多少种不同的颜色序列......
  • 【流水】2022.11.16
    不知道该流些什么今天他妈除了改题啥也没做,属实气死人自闭了大佬们一个个的夸夸切题我隔这一直就硬绷每次考后倒数着改完题什么人啊还能要吗?(大悲)草,今天得赶紧赶......
  • apache启动遇到phpinfo只显示源码问题
    在安装php和apache的时候,会遇到只显示源码的问题网上找了好多帖子都是在改php.ini的东西,但是改了半天也不对,发现我安装的wordpress目录也打不开,所以我认为这就是apache服......
  • vivo霍金实验平台设计与实践-平台产品系列02
    vivo霍金实验平台设计与实践-平台产品系列02https://mp.weixin.qq.com/s/Bg1POF_eosTPgGNK3VzVtgvivo霍金实验平台设计与实践-平台产品系列02原创 BaoDawei vivo互联......
  • Datawahle — 2022年11月组队学习 — 李宏毅机器学习 — TASK02
    学习时间:2022年11月15-2022年11月16日学习内容:李宏毅机器学习视频P3和P4学习笔记 ......
  • 第五章第5节: 2020.06.06 智能互联网之弹性容器云与Service Mesh【五】.
                                         ......
  • 2022-11-16学习内容
    1.案例-购物车-购物车列表展示1.1item_cart.xml<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"......
  • 2022.11.17
    T1给你一个质数,让你求首先,观察到,答案很小(最大的大样例也只有\(16\)),于是就打了个质数表,跑了下最大的质数看看,答案最大也就是31,于是很明显,\(a\)的最大值就到31,一个很小......
  • 2022_后台前端幕课网
    新建一个项目 vue3 命令 vuecreate****安装后发现版本低 可以使用以下指令升级版本,使支持最新setup语法npmivue@3.2.8vue-router@4.0.11vuex@4.0.2开发前期,......