我有以下请求上下文类,该类用于收集某些信息以供将来在Servlet过滤器中处理:

public class ApplicationRequestContext {
  private static final ThreadLocal<AppRequest> tl = new ThreadLocal<AppRequest>();

  public static void begin(HttpServletRequest httpRequest) {
    tl.set(getAppRequest(httpRequest));
  }

  public static void finish() {
    tl.remove();
  }
}


getAppRequest(httpRequest)仅返回一个对象。然后在Servlet过滤器中...

public class ApplicationServletFilter implements javax.servlet.Filter {
  @Override

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
      ApplicationRequestContext.begin(httpRequest);
      /* other stuff */
      chain.doFilter(httpRequest, httpResponse);
    } catch (Exception e) { /* … */ }
    finally {
      ApplicationRequestContext.finish();
    }
  }
}


我想知道,此设置是否可能有多个传入请求,以可能覆盖彼此的数据(getAppRequest(httpRequest)对象显然将是唯一的)?这甚至是线程安全的吗?

最佳答案

您必须记住,每个Thread都有自己的ThreadLocal-实际上,确切地说,是自己的ThreadLocal.ThreadLocalMap(我使用的是OpenJDK作为示例)。

当名为ThreadLocaltl调用其set() method时,它基本上会创建一个新的ThreadLocalMap并以tl作为对create a ThreadLocalMap.Entry的键的引用。

由于每个Servlet请求都使用一个唯一线程(从托管线程池或生成一个新线程,并且没有两个Servlet线程处理相同的请求),因此tl.set()拥有该ThreadLocal的新创建的作为对该Servlet ThreadLocalMapThread的引用。

现在,当ThreadLocal.ThreadLocalMap is called时,我们只需获取Servlet tl.get()Thread,然后执行lookup with ThreadLocalMap以获取我们输入的值,例如ThreadLocalMap.getEntry()

这里要记住的要点是,是的,您正在使用一个名为getAppRequest(httpRequest)的单个ThreadLocal对象,但是每个tl在这种情况下都是Servlet容器用来处理每个请求(包括其过滤器)的线程(s),将具有其自己的Thread,并带有对此ThreadLocal.ThreadLocalMap对象的[弱]引用作为其键。

因此,ThreadLocal只是t1ThreadLocal.ThreadLocalMap.Entry)表中的键,用于获取tl.ThreadLocalMap.EntryThread,这对于该线程是唯一的。因此,它是线程安全的,并且这些LocalThread.ThreadLocalMapbegin()调用基本上将数据放入每个finish()中。

关于java - 该LocalThread可以覆盖其他Servlet请求的数据吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57154698/

10-11 04:01