netty源码阅读之性能优化工具类之FastThreadLocal的set方法实现

38 篇文章 1 订阅
33 篇文章 1 订阅

FastThreadLocal的set方法实现我们从以下三点分析:

1、获取ThreadLocalMap

2、直接通过索引set对象

3、如果需要remove对象,那就remove

我们还是从set方法源码开始:

    /**
     * Set the value for the current thread.
     */
    public final void set(V value) {
        if (value != InternalThreadLocalMap.UNSET) {
            set(InternalThreadLocalMap.get(), value);
        } else {
            remove();
        }
    }

一、获取ThreadLocalMap

获取ThreadLocalMap的方法还是和之前的一样调用这个方法InternalThreadLocalMap.get(),不多解释了,可以看上一篇文章。

二、直接通过索引set对象

那么我们看set的源码:


    /**
     * Set the value for the specified thread local map. The specified thread local map must be for the current thread.
     */
    public final void set(InternalThreadLocalMap threadLocalMap, V value) {
        if (value != InternalThreadLocalMap.UNSET) {
            if (threadLocalMap.setIndexedVariable(index, value)) {
                addToVariablesToRemove(threadLocalMap, this);
            }
        } else {
            remove(threadLocalMap);
        }
    }

如果设置进来的值不是UNSET那么久把值设置进去,

     * @return {@code true} if and only if a new thread-local variable has been created
     */
    public boolean setIndexedVariable(int index, Object value) {
        Object[] lookup = indexedVariables;
        if (index < lookup.length) {
            Object oldValue = lookup[index];
            lookup[index] = value;
            return oldValue == UNSET;
        } else {
            expandIndexedVariableTableAndSet(index, value);
            return true;
        }
    }

设置值还是只要把对象放到特定的索引位置就可以了,注意我们还是返回了 oldValue==UNSET。也就是,我们返回了之前的值是否为unset,返回之后,如果为unset,那么就要调用addToVariablesToRemove。

 

 

三、如果需要remove对象,那就remove

我们之前看到了一个这个remove(threadLocalMap);

看源码:

    /**
     * Sets the value to uninitialized for the specified thread local map;
     * a proceeding call to get() will trigger a call to initialValue().
     * The specified thread local map must be for the current thread.
     */
    @SuppressWarnings("unchecked")
    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);
            }
        }
    }

看这个removeIndexedVariable方法:


    public Object removeIndexedVariable(int index) {
        Object[] lookup = indexedVariables;
        if (index < lookup.length) {
            Object v = lookup[index];
            lookup[index] = UNSET;
            return v;
        } else {
            return UNSET;
        }
    }

其实很简单,就是把索引所在位置的对象设置为UNSET对象。

还有一个removeFromVariablesToRemove(threadLocalMap, this);和前面的addToVariablesToRemove相对应。

目前我们知道有两种情况需要addToVariables的:

1、在set之后,set之前老值为UNSAFE的。

2、在调用get之后,没有对象然后调用initial方法给赋值的再返回的。

有一种情况需要removeFromVariables的:

1、在remove也就是设置一个index的值为UNSET之后。

最后一个:

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

如果移除的对象是用户设置进去的,那么就调用onRemoval方法,这个方法可以在用户代码里面覆盖,例如:

    private static FastThreadLocal<Object> threadLocal = new FastThreadLocal<Object>() {
        @Override
        protected Object initialValue() {
            return new Object();
        }

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

那么当我们移除这个数据的时候,我们就知道被移除了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值