未为 java 中的下一个线程清除 ThreadLocal 值
ThreadLocal value not cleared for the next thread in java
我是 运行 至少接收 200 RPS 的 Web 服务。根据操作,我们为少数操作提供 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()
方法将return 实际调用者基于请求。问题是 200 个请求中有 1 个请求 returns root
而不是实际调用者。
我注意到的一件事是我没有使用 threadlocal.remove(),而是将该值设置为 null。预计 getRunner() rootContext.get() != null
条件将失败并且 return 实际调用者。
如何解决这个问题?设置 rootContext.remove()
会解决这个问题吗?如果是,如何?
感谢您的帮助
您的 rootAccess
方法有两个问题:
- 如果 Runnable 抛出 RuntimeException,则不会删除 ThreadLocal(可能是您所看到的)
rootContext.set(null);
仍然保留与 运行 线程关联的 ThreadLocal
实例,最好做 rootContext.remove();
更正这两点就是把rootAccess()
改成
public void rootAccess(Runnable runnable) {
rootContext.set("root");
try {
runnable.run();
} finally {
rootContext.remove();
}
}
为什么 rootContext.set(null);
通常是个问题?
每个线程基本上都有一个类似于 Map<ThreadLocal, ?>
的数据结构,其中键是您的 ThreadLocal
实例 (rootContext
),值是您通过它关联的值rootContext.set(xx);
如果您调用 rootContext.set(null);
,那么 rootContext
仍在该映射中,因此执行此行的每个线程(来自线程池,这意味着线程很长 运行)保留对 rootContext
的引用可能会阻止 class 卸载。
如果您调用 rootContext.remove();
,rootContext
将从该地图中删除。
我是 运行 至少接收 200 RPS 的 Web 服务。根据操作,我们为少数操作提供 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()
方法将return 实际调用者基于请求。问题是 200 个请求中有 1 个请求 returns root
而不是实际调用者。
我注意到的一件事是我没有使用 threadlocal.remove(),而是将该值设置为 null。预计 getRunner() rootContext.get() != null
条件将失败并且 return 实际调用者。
如何解决这个问题?设置 rootContext.remove()
会解决这个问题吗?如果是,如何?
感谢您的帮助
您的 rootAccess
方法有两个问题:
- 如果 Runnable 抛出 RuntimeException,则不会删除 ThreadLocal(可能是您所看到的)
rootContext.set(null);
仍然保留与 运行 线程关联的ThreadLocal
实例,最好做rootContext.remove();
更正这两点就是把rootAccess()
改成
public void rootAccess(Runnable runnable) {
rootContext.set("root");
try {
runnable.run();
} finally {
rootContext.remove();
}
}
为什么 rootContext.set(null);
通常是个问题?
每个线程基本上都有一个类似于 Map<ThreadLocal, ?>
的数据结构,其中键是您的 ThreadLocal
实例 (rootContext
),值是您通过它关联的值rootContext.set(xx);
如果您调用 rootContext.set(null);
,那么 rootContext
仍在该映射中,因此执行此行的每个线程(来自线程池,这意味着线程很长 运行)保留对 rootContext
的引用可能会阻止 class 卸载。
如果您调用 rootContext.remove();
,rootContext
将从该地图中删除。