Hit*_*esh 8 java multithreading thread-local
我在下面的博客上看到了ThreadLocals的概念:
https://www.baeldung.com/java-threadlocal
它说"不要将ThreadLocal与ExecutorService一起使用"
它说明了下面使用ThreadLocals的示例.
public class ThreadLocalWithUserContext implements Runnable {
private static ThreadLocal<Context> userContext
= new ThreadLocal<>();
private Integer userId;
private UserRepository userRepository = new UserRepository();
@Override
public void run() {
String userName = userRepository.getUserNameForUserId(userId);
userContext.set(new Context(userName));
System.out.println("thread context for given userId: "
+ userId + " is: " + userContext.get());
}
// standard constructor
}
Run Code Online (Sandbox Code Playgroud)
在帖子的最后,它提到:
"如果我们想使用ExecutorService并向其提交Runnable,那么使用ThreadLocal将产生非确定性结果 - 因为我们无法保证每次给定userId的每个Runnable操作都将由同一个线程处理执行.
因此,我们的ThreadLocal将在不同的userId之间共享.这就是为什么我们不应该将TheadLocal与ExecutorService一起使用.只有当我们完全控制哪个线程将选择要执行哪个可运行动作时,才应该使用它."
这个解释对我来说是一个保镖.我特意在网上做了一些研究,但是我得不到多少帮助,有些专家请详细说明上述解释吗?它是作者观点还是真正的威胁?
将 ThreadLocal 视为由同一线程执行的代码的某种“内存缓存”。完全相同的线程。在不同线程上执行的代码之间共享 ThreadLocal 是一个坏主意。
Tha javadoc 明确指出:
此类提供线程局部变量。这些变量不同于它们的普通对应变量,因为每个访问一个(通过其 get 或 set 方法)的线程都有自己的、独立初始化的变量副本。ThreadLocal 实例通常是希望将状态与线程相关联的类中的私有静态字段(例如,用户 ID 或事务 ID)。
换句话说:使用 ThreadLocals的目标是为在不同线程中运行的“每个”代码提供“线程特定”数据。
另一方面,ExecutorService 首先是一个接口:您根本不知道它是由单个线程提供支持,还是(更有可能)由多个线程提供支持。
换句话说:使用 ExecutorService 会很快导致多个不同的线程运行您的 Runnables/Tasks。然后您将在这些多个线程之间共享您的 ThreadLocal。
因此,“危险”可能是错误的词。使用 ThreadLocal的目标是拥有每个线程的存储,而 ExecutorService 是关于由未知数量的线程执行的代码。这两件事根本不能很好地结合在一起。
重点不同:一个概念强调与非常具体的“活动”相关的长期存在的线索。另一个概念是关于使用未知数量的无名线程执行小的、独立的活动。
需要注意的是,您的多次Runnable运行可能会在不同的线程上执行。执行程序服务可以由单个线程支持,但也可以由线程池支持。在您的后续执行中Runnable,不同的线程将访问不同的ThreadLocal.
因此,您当然可以ThreadLocal在一次运行中使用Runnable. 但它不太可能有用,因为通常 a 的目的ThreadLocal是暂时保留一个值。相反,aRunnable通常应该是短暂的。
ThreadLocal所以,不,通常将 a与线程池一起使用是没有意义的。
| 归档时间: |
|
| 查看次数: |
1812 次 |
| 最近记录: |