为了账号安全,请及时绑定邮箱和手机立即绑定

请问为什么不能直接使用一个Thread和Value绑定的Map?

请问一下哈,自定义的ThreadLocal中,为什么不能直接声明一个Map<Thread, T> 来保存value,而是要再套一个map?

正在回答

4 回答

秋田君说的也很不错, 我这里补充下, Map<Thread, T>这种结构,hash表冲突会很严重,举个例子。map.put(thread1, 100);map.put(thread1, 200);map.put(thread1, 300);你发现没有,一个map put了三个值,那取值的时候, 怎么办呢?

1 回复 有任何疑惑可以回复我~

同样的 main 函数,使用老师的代码执行会发现主线程不同 MyThreadLocal 实例中的数据是互不影响互不干扰的

public static void main(String[] args) {
    MyThreadLocal<Long> userIdContext = new MyThreadLocal<>() {
        @Override
        protected Long initialValue() {
            return 1L;
        }
    };
    MyThreadLocal<Connection> connectionContext = new MyThreadLocal<>();

    System.out.println(userIdContext.get()); // 1
    System.out.println(connectionContext.get()); // null
}


1 回复 有任何疑惑可以回复我~

从使用上看应该是为了不同场景使用时数据隔离,同一线程之间不同 MyThreadLocal 实例间的数据隔离

@Deprecated
public class MyThreadLocalWrong<T> {

    private static Map<Thread, Object> threadLocalMap = new HashMap<>();

    protected T initialValue() {
        return null;
    }

    public synchronized T get() {
        return (T) threadLocalMap.computeIfAbsent(Thread.currentThread(), t -> initialValue());
    }

    public synchronized void set(T t) {
        threadLocalMap.put(Thread.currentThread(), t);
    }

    public static void main(String[] args) {
        MyThreadLocalWrong<Long> userIdContext = new MyThreadLocalWrong<>() {
            @Override
            protected Long initialValue() {
                return 1L;
            }
        };
        MyThreadLocalWrong<Connection> connectionContext = new MyThreadLocalWrong<>();

        System.out.println(userIdContext.get()); // 1
        System.out.println(connectionContext.get()); // 1
    }
}

如果直接使用 Map<Thread, T> 来存储数据,由于 threadLocalMap 是静态变量,那么同一线程不同 MyThreadLocal 实例存储时,数据会被覆盖,读取数据时,会得到错乱的值!

5 回复 有任何疑惑可以回复我~

应该为了解耦

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消

请问为什么不能直接使用一个Thread和Value绑定的Map?

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信