这个 LocalThread 会覆盖其他 Servlet 请求的数据吗?
Could This LocalThread Overwrite Other Servlet Requests' Data?
我有以下请求上下文 class 用于收集某些信息以供将来在 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)
只是 returns 一个对象。在 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-safe。而且,它不能覆盖彼此的数据。
因为,
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html
您必须记住,每个 Thread
都有自己的 ThreadLocal
—— 实际上,准确地说,是自己的 ThreadLocal.ThreadLocalMap
(我使用 OpenJDK 作为示例)。
当您的名为 tl
的 ThreadLocal
调用其 set()
method, it basically creates a new ThreadLocalMap
and have tl
as a reference as a key to create a ThreadLocalMap.Entry
。
由于每个 Servlet 请求都使用一个唯一的线程(来自托管线程池或生成一个新线程,并且没有两个 Servlet 线程处理相同的请求),因此 tl.set()
ThreadLocal
的新创建 ThreadLocalMap
作为对该 Servlet Thread
的 ThreadLocal.ThreadLocalMap
.
的引用
现在,当 tl.get()
is called, we simply get the Servlet Thread
's ThreadLocalMap
, and do a lookup with ThreadLocalMap.getEntry()
时,获取我们输入的值,例如getAppRequest(httpRequest)
.
这里要记住的要点是,是的,您正在使用一个名为 tl
的 ThreadLocal
对象,但每个 Thread
,在这种情况下,一个线程用于处理每个请求的 Servlet 容器,包括其过滤器,将拥有自己的 ThreadLocal.ThreadLocalMap
,并将此 ThreadLocal
对象的 [weak] 引用作为其键。
因此,t1
只是 ThreadLocal.ThreadLocalMap.Entry
(tl.ThreadLocalMap.Entry
) 的 table 中的一个键,用于获取 Thread
的 LocalThread.ThreadLocalMap
这是该线程独有的。因此,它是 thread-safe,那些 begin()
和 finish()
调用基本上是在每个 Thread
中放入数据。
我有以下请求上下文 class 用于收集某些信息以供将来在 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)
只是 returns 一个对象。在 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-safe。而且,它不能覆盖彼此的数据。
因为,
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html
您必须记住,每个 Thread
都有自己的 ThreadLocal
—— 实际上,准确地说,是自己的 ThreadLocal.ThreadLocalMap
(我使用 OpenJDK 作为示例)。
当您的名为 tl
的 ThreadLocal
调用其 set()
method, it basically creates a new ThreadLocalMap
and have tl
as a reference as a key to create a ThreadLocalMap.Entry
。
由于每个 Servlet 请求都使用一个唯一的线程(来自托管线程池或生成一个新线程,并且没有两个 Servlet 线程处理相同的请求),因此 tl.set()
ThreadLocal
的新创建 ThreadLocalMap
作为对该 Servlet Thread
的 ThreadLocal.ThreadLocalMap
.
现在,当 tl.get()
is called, we simply get the Servlet Thread
's ThreadLocalMap
, and do a lookup with ThreadLocalMap.getEntry()
时,获取我们输入的值,例如getAppRequest(httpRequest)
.
这里要记住的要点是,是的,您正在使用一个名为 tl
的 ThreadLocal
对象,但每个 Thread
,在这种情况下,一个线程用于处理每个请求的 Servlet 容器,包括其过滤器,将拥有自己的 ThreadLocal.ThreadLocalMap
,并将此 ThreadLocal
对象的 [weak] 引用作为其键。
因此,t1
只是 ThreadLocal.ThreadLocalMap.Entry
(tl.ThreadLocalMap.Entry
) 的 table 中的一个键,用于获取 Thread
的 LocalThread.ThreadLocalMap
这是该线程独有的。因此,它是 thread-safe,那些 begin()
和 finish()
调用基本上是在每个 Thread
中放入数据。