netty源码-FastThreadLocal

5 篇文章 0 订阅
4 篇文章 0 订阅

FastThreadLocal

基本使用

private static final FastThreadLocal<String> FAST_THREAD_LOCAL = new FastThreadLocal<String>() {
    @Override
    protected String initialValue() throws Exception {
        return "Hello World!";
    }
};

public static void main(String[] args) {
    String value = FAST_THREAD_LOCAL.get();
    System.out.println(value);
}

构造方法

在通过构造方法创建FastThreadLocal时,会在其内部初始化一个索引值index:

// 初始化index 在后面会用到
public FastThreadLocal() {
    index = InternalThreadLocalMap.nextVariableIndex();
}
// 初始化时通过 InternalThreadLocalMap 获取索引
public static int nextVariableIndex() {
    int index = nextIndex.getAndIncrement();
    if (index < 0) {
        nextIndex.decrementAndGet();
        throw new IllegalStateException("too many thread-local indexed variables");
    }
    return index;
}

通过这个构造方法我们可以获取一个信息:当前线程每实例化一个FastThreadLocal,都将提供一个自增的index。

FastThreadLocal.get()

public final V get() {
    // 获取当前线程变量
    InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
    Object v = threadLocalMap.indexedVariable(index);
    if (v != InternalThreadLocalMap.UNSET) {
        return (V) v;
    }
    return initialize(threadLocalMap);
}

和ThreadLocal相同,FastThreadLocal的作用也是获取当前线程在该ThreadLocal中存储的变量,不过方式有所不同,继续往下看。

InternalThreadLocalMap.get()

这个方法根据当前线程是否是FastThreadLocalThread来判断是否使用FastThreadLocal:

public static InternalThreadLocalMap get() {
    Thread thread = Thread.currentThread();// 当前线程
    if (thread instanceof FastThreadLocalThread) {// 判断当前线程是否 FastThreadLocalThread
        return fastGet((FastThreadLocalThread) thread);
    } else {
        return slowGet();// 如果不是FastThreadLocalThread就使用普通方式
    }
}

fastGet和slowGet的区别

当前线程是FastThreadLocalThread时,将会为当前线程变量初始化InternalThreadLocalMap(还没初始化时),这里会创建一个InternalThreadLocalMap:

private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {
    InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();
    if (threadLocalMap == null) {
        thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());
    }
    return threadLocalMap;
}

如果当前线程不是FastThreadLocalThread时,将会利用InternalThreadLocalMap中的常量 slowThreadLocalMap 来保存初始化的 InternalThreadLocalMap,等于这里没有持有直接引用,而是把InternalThreadLocalMap保存到了当前线程的线程变量中:

private static InternalThreadLocalMap slowGet() {
    InternalThreadLocalMap ret = slowThreadLocalMap.get();
    if (ret == null) {
        ret = new InternalThreadLocalMap();
        slowThreadLocalMap.set(ret);
    }
    return ret;
}

InternalThreadLocalMap

其内部使用数组的结构,初始化时将会创建实例化一个长度为32的数组(当然长度不足时也会涉及到扩容机制):

private InternalThreadLocalMap() {
    indexedVariables = newIndexedVariableTable();
}

private static Object[] newIndexedVariableTable() {
    Object[] array = new Object[INDEXED_VARIABLE_TABLE_INITIAL_SIZE];// 长度32
    Arrays.fill(array, UNSET);
    return array;
}

前面我们已经知道在FastThreadLocal初始化时已经为其获取了索引index,接下来回到FastThreadLocal的get方法:

public final V get() {
    // 获取当前线程变量
    InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
    Object v = threadLocalMap.indexedVariable(index);
    if (v != InternalThreadLocalMap.UNSET) {
        return (V) v;
    }
    return initialize(threadLocalMap);
}

通过indexedVariable(index)来获取当前FastThreadLocal的线程变量。

其实到这里我们可以发现,Netty在这里创建的Object数组是一种空间换时间的方式,使得对线程变量的使用得到了优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值