[英]ThreadLocal value not cleared for the next thread in java
I'm running a web service which is receiving 200 RPS at least.我正在运行 web 服务,该服务至少接收 200 RPS。 Based on the action, we provide root access for few operations and using the following code.基于该操作,我们为少数操作提供 root 访问权限,并使用以下代码。
private static final ThreadLocal<String> rootContext = new ThreadLocal<String>();
public Optional<String> getRunner() {
if (rootContext.get() != null) {
return rootContext.get();
} else {
return getCurrentRunner();
}
}
public void rootAccess(Runnable runnable) {
rootContext.set("root");
runnable.run();
rootContext.set(null);
}
getCurrentRunner()
method will return the actual caller based on the request. getCurrentRunner()
方法将根据请求返回实际的调用者。 The problem is 1 request out of 200 requests returns root
instead of the actual caller.问题是 200 个请求中有 1 个返回root
而不是实际的调用者。
One thing I noticed is instead of using threadlocal.remove(), I'm setting that value as null.我注意到的一件事是,我没有使用 threadlocal.remove(),而是将该值设置为 null。 Expecting that, getRunner() rootContext.get() != null
condition will fail and return the actual caller.预计 getRunner() rootContext.get() != null
条件将失败并返回实际的调用者。
How to solve this?如何解决这个问题? Will setting rootContext.remove()
solve this?设置rootContext.remove()
会解决这个问题吗? If yes, how?如果是,如何?
Thanks for the help谢谢您的帮助
There are two problems with your rootAccess
method:您的rootAccess
方法有两个问题:
rootContext.set(null);
still keeps the ThreadLocal
instance associated with the running thread, it is better to do rootContext.remove();
仍然保持与正在运行的线程关联的ThreadLocal
实例,最好做rootContext.remove();
Correcting this two points means to change rootAccess()
to更正这两点意味着将rootAccess()
更改为
public void rootAccess(Runnable runnable) {
rootContext.set("root");
try {
runnable.run();
} finally {
rootContext.remove();
}
}
Why is rootContext.set(null);
为什么是rootContext.set(null);
generally a problem?一般有问题吗?
Each thread basically keeps a data structure similar to a Map<ThreadLocal, ?>
where the key is your ThreadLocal
instance ( rootContext
) and the value is the value that you associate with it through rootContext.set(xx);
每个线程基本上都保留一个类似于Map<ThreadLocal, ?>
的数据结构,其中键是您的ThreadLocal
实例( rootContext
),值是您通过rootContext.set(xx);
If you call rootContext.set(null);
如果你调用rootContext.set(null);
then rootContext
is still in that map and therefore each thread (from a thread pool, meaning the thread is long running) that executed this line keeps a reference to rootContext
which in turn might prevent class unloading.那么rootContext
仍然在 map 中,因此执行此行的每个线程(来自线程池,意味着线程长时间运行)都会保留对 rootContext 的引用,这反过来可能会阻止rootContext
卸载。
If you call rootContext.remove();
如果你调用rootContext.remove();
the rootContext
is removed from that map. rootContext 从rootContext
中删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.