每天了解一个新知识--------ThreadLocal线程隔离工具

0 阅读1分钟

ThreadLocal 是 JDK 提供的用于实现线程封闭的工具类。

我们可以实例项目应用一下:在 context 包下创建一个工具类(如 BaseContext),在其中静态实例化 ThreadLocal,并封装 set、get 和 remove 方法供全局调用。

注:像这种new对象的方式来创建ThreadLocal 其是没有默认值的

a9d18d2f-8209-4701-86d0-1d298e0c2364.png

原理: 当请求进入时,拦截器解析 Token 获取用户 ID,并通过 set 方法将其绑定到当前执行线程上。 当请求结束时,必须调用 remove 方法清除数据。这样做有两个核心目的:

1 防止数据串扰:避免线程复用时,后续请求读到前一个用户的敏感信息

2 防止内存泄漏:确保在线程池长期运行的环境下,废弃的对象能被 GC 及时回收。

而ThreadLocal 的值保存在ThreadLocalMap这样的结构中,这种结构是一个非常类似与HashMap的结构,他以ThreadLocal作为KEY,value就是ThreadLocal的值每个线程都有一个ThreadLocalMap对象。

如下:

91e7b808-1efe-481a-b755-c831fcc7d566.png


static class ThreadLocalMap {

    static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }

    private static final int INITIAL_CAPACITY = 16;
    private Entry[] table;
    private int size = 0;
    private int threshold; // Default to 0

    private void setThreshold(int len) {
        threshold = len * 2 / 3;
    }

    private static int nextIndex(int i, int len) {
        return ((i + 1 < len) ? i + 1 : 0);
    }

    private static int prevIndex(int i, int len) {
        return ((i - 1 >= 0) ? i - 1 : len - 1);
    }

    ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
        table = new Entry[INITIAL_CAPACITY];
        int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
        table[i] = new Entry(firstKey, firstValue);
        size = 1;
        setThreshold(INITIAL_CAPACITY);
    }
}