TransmittableThreadLocal简单理解及使用

发布于:2024-04-05 ⋅ 阅读:(19) ⋅ 点赞:(0)

TransmittableThreadLocal 简单理解及使用

TransmittableThreadLocal 是对普通 ThreadLocal 的增强,它能够在多线程环境中安全地传递线程本地变量,并且能够在线程池中使用,但相应地可能会带来一定的性能开销。

首先回顾一下ThreadLocal的概念:

一个程序就像一个医院,系统线程像是护士长,负责管理和分配任务给各个护士。每个用户线程就像是一个护士,她处理着用户的一次请求(病人的一次需求)。 而这时候ThreadLocal就是每个护士的大脑记忆,它需要记住对应的病人的一次需求内容是啥(用来记录和存储当前正在处理的用户请求的相关信息)。可是情况不是固定的,病人可能有着很多的需求,病人可能前一会是想要测血压;几秒后又想打葡萄糖了,这样子这两个需求是不同的,这个时候的ThreadLocal就起到作用了,它是属于每个护士独立的记忆,所以这样需求对象就不会被覆盖啥的。(这样可以确保不同的用户请求不会相互干扰,避免出现数据错乱或混乱的情况。)

在这个例子上,补充一下TransmittableThreadLocal:

而与普通的 ThreadLocal 不同,TransmittableThreadLocal 能够在不同的护士(线程)之间传递和复制大脑记忆,从而确保病人的需求能够在不同护士之间正确传递,不会丢失或混乱。

具体来说,在医院的例子中,当护士 A 需要协助处理病人 X 的需求时,她可能会将自己的大脑记忆(TransmittableThreadLocal 中记录的信息)传递给另一个护士 B,让 B 知道病人 X 需要做的检查项目或治疗方案。而由于使用了 TransmittableThreadLocal,护士 B 可以正确地获取到护士 A 的大脑记忆,并继续协助处理病人 X 的需求,而不会丢失 A 记录的信息或出现数据混乱的情况。

在这个例子中,TransmittableThreadLocal 具有将线程本地变量值在多个线程之间传递的能力,使得不同线程之间能够共享和传递数据,而不会丢失或出现数据混乱的情况。

使用案例:

import com.alibaba.ttl.TransmittableThreadLocal;


public class XXXLocalThread {
    private static final TransmittableThreadLocal<XXX> threadLocal = new TransmittableThreadLocal<>(); 

    public static XXX getXXX() {
        return threadLocal.get();
    }

    public static void set(XXX xxx) {
        threadLocal.set(xxx);
    }

    public static void remove() {
        threadLocal.remove();
    }
}

日常使用场景:

Web 请求上下文传递: 在处理 Web 请求时,可能会在主线程中设置一些请求相关的信息(例如用户信息、请求 ID 等),然后在异步任务中继续使用这些信息。使用 TransmittableThreadLocal 可以确保在主线程和异步任务中能够正确地传递和使用这些请求上下文信息,而不会出现丢失或混乱。

public class RequestContext {
    private static final TransmittableThreadLocal<RequestInfo> requestInfoThreadLocal = new TransmittableThreadLocal<>();

    public static void setRequestInfo(RequestInfo requestInfo) {
        requestInfoThreadLocal.set(requestInfo);
    }

    public static RequestInfo getRequestInfo() {
        return requestInfoThreadLocal.get();
    }
}

日志追踪: 在日志记录中,可能需要在不同线程中记录同一个请求的日志信息,以便进行请求追踪和调试。使用 TransmittableThreadLocal 可以确保日志记录器能够在不同线程之间正确传递和使用请求相关的日志上下文信息,而不会丢失或混乱。

public class LoggerContext {
    private static final TransmittableThreadLocal<String> requestIdThreadLocal = new TransmittableThreadLocal<>();

    public static void setRequestId(String requestId) {
        requestIdThreadLocal.set(requestId);
    }

    public static String getRequestId() {
        return requestIdThreadLocal.get();
    }
}

缓存处理: 在缓存处理中,可能需要在多个线程中共享同一个缓存对象,并且需要在不同线程中更新和读取缓存数据。使用 TransmittableThreadLocal 可以确保缓存对象在不同线程之间正确传递和共享数据,而不会出现数据不一致的情况。

public class CacheManager {
    private static final TransmittableThreadLocal<Map<String, Object>> cacheThreadLocal = new TransmittableThreadLocal<>(); 

    public static void put(String key, Object value) {
        Map<String, Object> cache = cacheThreadLocal.get();
        if (cache == null) {
            cache = new HashMap<>();
            cacheThreadLocal.set(cache);
        }
        cache.put(key, value);
    }

    public static Object get(String key) {
        Map<String, Object> cache = cacheThreadLocal.get();
        return cache != null ? cache.get(key) : null;
    }
}

任务分发和处理: 在任务分发和处理的场景中,可能需要在不同线程中共享任务相关的上下文信息,并且需要在不同线程中正确处理和传递任务。使用 TransmittableThreadLocal 可以确保任务相关的上下文信息能够在不同线程之间正确传递和使用,从而确保任务的正确处理和执行。

public class TaskContext {
    private static final TransmittableThreadLocal<TaskInfo> taskInfoThreadLocal = new TransmittableThreadLocal<>();

    public static void setTaskInfo(TaskInfo taskInfo) {
        taskInfoThreadLocal.set(taskInfo);
    }

    public static TaskInfo getTaskInfo() {
        return taskInfoThreadLocal.get();
    }
}