使用 ThreadLocal

Java Concurrency 中一个有用的工具是 ThreadLocal - 这允许你拥有一个对给定线程唯一的变量。因此,如果相同的代码在不同的线程中运行,则这些执行将不共享该值,而是每个线程都有自己的线程本地变量。

例如,这经常用于建立处理 servlet 中的请求的上下文(例如授权信息)。你可能会这样做:

private static final ThreadLocal<MyUserContext> contexts = new ThreadLocal<>();

public static MyUserContext getContext() {
    return contexts.get(); // get returns the variable unique to this thread
}

public void doGet(...) {
    MyUserContext context = magicGetContextFromRequest(request); 
    contexts.put(context); // save that context to our thread-local - other threads
                           // making this call don't overwrite ours
    try {
        // business logic
    } finally {
        contexts.remove(); // 'ensure' removal of thread-local variable
    }
}

现在,你可以在需要的地方使用 MyServlet.getContext(),而不是将 MyUserContext 传递到每个方法中。当然,这确实引入了一个需要记录的变量,但它是线程安全的,这消除了使用这种高范围变量的许多缺点。

这里的关键优势是每个线程在 contexts 容器中都有自己的线程局部变量。只要你从定义的入口点使用它(比如要求每个 servlet 维护其上下文,或者可能通过添加 servlet 过滤器),你可以在需要时依赖此上下文。