Netty源码之FastThreadLocal

我们都知道在jdk中有一个ThreadLocal,让每个线程都有一个独享的变量,Netty也是多线程工作的,所有它也需要这么一个机制,不出乎意料,果然他有一个FastThreadLocal,比jdk的ThreadLocal更快,接下来,我们就来感受一下他的源码。下面时代码的入口:

public class FastThreadLocalTest {
    private static FastThreadLocal<Object> threadLocal0 = new FastThreadLocal<Object>() {
        @Override
        protected Object initialValue() {
            return new Object();
        }

        @Override
        protected void onRemoval(Object value) throws Exception {
            System.out.println("onRemoval");
        }
    };

    public static void main(String[] args) {
        new Thread(() -> {
            Object object = threadLocal0.get();
            // .... do with object
            System.out.println(object);
            threadLocal0.set(new Object());

        }).start();

        new Thread(() -> {
            Object object = threadLocal0.get();
            System.out.println(object);
            while (true) {
                System.out.println(threadLocal0.get() == object);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

首先我们来看一下他是如何创建的:

public FastThreadLocal() {
        index = InternalThreadLocalMap.nextVariableIndex();
    }

它的构造方法就只是获得了一个索引,在jvm中FastThreadLocal是以这个索引来区别的,它的生成方式是从0开始递增。
下面来看一下他的get方法:

public final V get() {
        return get(InternalThreadLocalMap.get());
    }

他首先是从自己内部维护的一个map中调用get方法:

public static InternalThreadLocalMap get() {
		//首先获取当前线程
        Thread thread = Thread.currentThread();
        //获取InternalThreadLocalMap
        if (thread instanceof FastThreadLocalThread) {
            return fastGet((FastThreadLocalThread) thread);
        } else {
            return slowGet();
        }
    }

根据当前线程执行不同的逻辑:

private static InternalThreadLocalMap slowGet() {
		//这是一个jdk底层的ThreadLocal
        ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap;
        //从ThreadLocal中获得当前线程所对应的InternalThreadLocalMap 
        InternalThreadLocalMap ret = slowThreadLocalMap.get();
        //如果为空需要进行初始化
        if (ret == null) {
            ret = new InternalThreadLocalMap();
            slowThreadLocalMap.set(ret);
        }
        return ret;
    }

我们发现FastThreadLocal底层是利用了jdk的TheadLocal来保存每个线程的InternalThreadLocalMap对象。

public final V get(InternalThreadLocalMap threadLocalMap) {
        Object v = threadLocalMap.indexedVariable(index);
        if (v != InternalThreadLocalMap.UNSET) {
            return (V) v;
        }

        return initialize(threadLocalMap);
    }

然后从当前线程的threadLocalMap里面根据当前FastTheadLocal下标来获取对象:

public Object indexedVariable(int index) {
        Object[] lookup = indexedVariables;
        return index < lookup.length? lookup[index] : UNSET;
    }

每个线程的threadLocalMap里面维护了一个数组,而数组的下标对应的就是当前FastTheadLocal唯一标识好,就直接根据这个index从数组中取得对象,时间复杂度是O(1),这也就是Netty中FastThreadLocal快的地方,而线程set对象的时候也是根据FastThreadLocal的index将threadLocalMap数组里面对应的位置set上去。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值