gpt4 book ai didi

java - 私有(private)静态最终实例的线程局部行为

转载 作者:行者123 更新时间:2023-11-30 07:38:06 25 4
gpt4 key购买 nike

你好,我有这样的类定义

public class JdbcInterceptor {
private static final JdbcInterceptor instance = new JdbcInterceptor();
private static ThreadLocal<Boolean> dontIntercept = new ThreadLocal<Boolean>();
public static JdbcInterceptor getInstance() {
return instance;
}
public void skipIntercept() {
dontIntercept.set(true);
}
public boolean interrupt() {
boolean di = dontIntercept.get()!=null?dontIntercept.get().booleanValue():false;
if (di) {
dontIntercept.set(false);
}
return di;
}// end interrupt
}// end class

我在其他类(class)做这个

//class1 stuff
JdbcInterceptor.getInstance().skipIntercept();
if(JdbcInterceptor.getInstance().interrupt())
{ // class1 stuff happens
}

现在我在 class2 做这个

//class2 stuff
if(JdbcInterceptor.getInstance().interrupt())
{ // class2 stuff happens
}

现在我有点困惑,我知道 class1 的事情会发生,因为我设置了不要拦截 ThreadLocal。我怀疑 class2 的东西是否会发生?我的逻辑是,我只有一个 JdbcInterceptor 实例,因此在对 interrupt() 的所有调用中都应该有相同的状态。但有人告诉我,ThreadLocals 对于每个线程都是本地的。我在这里看到了一些冲突。请帮我解决这个问题。

最佳答案

你的问题不是很清楚。

But I have been told that ThreadLocals are local for each thread. I see some conflict here.

这是正确的。没有冲突。使用 ThreadLocal 存储的值对象对于每个线程都是唯一的。它实际上在内部与 Thread 对象一起存储,因此当一个线程终止 all 时,线程局部值也将被删除并可用于垃圾回收,除非有来自其他对象的其他引用线程。

如果您的两个类都使用同一个线程执行,那么除非您在两次调用之间更改本地线程的值,否则两者将具有相同的结果。如果不同的线程执行 class2,那么两者将具有不同的值(根据您的示例)。

您可能混淆了发生在时间和类/方法存储和代码中的线程执行。这两个是非常不同的。一个线程可以执行任何和所有方法,或者您可以让多个线程在一个类中执行相同的方法。您无法在代码中“看到”线程。如果没有其他图片,您必须想象它们 - 这确实需要一些仔细的可视化。

现在您可以使用 ThreadLocal 初始化程序使您的代码更清晰一些,如下所示:

private static ThreadLocal<Boolean> dontIntercept = new ThreadLocal<Boolean>() {

@Override
protected Boolean initialValue() {
return Boolean.FALSE;
}

};

然后当您使用本地线程时,您不必检查它是否为 null,如下所示:

public boolean interrupt() {
return dontIntercept.get().booleanValue();
}// end interrupt

这里尝试展示如何用更多的两个线程执行:

 Thread1 start---class1(skip=false)-+-skip(true)---+class1(true)--+class2(true)----+-end
| | | | |
Thread2 start---+-class1(false)+--------------+class2(false)---+-class1(false)---end

当我显示 classN(val) 时,该值是当时设置的跳过线程局部变量。

为了更具体地回答您的问题,请在本示例中:当线程 1 执行时,class1 和 class2 代码都将被跳过。当由 thread2 执行时,它们不会被跳过。

请注意,还有另一种本地线程称为InheritableThreadLocal。这在我的示例中会有所不同,因为 Thread2 会在线程启动第二个线程时继承 Thread1 中的值。

编辑 如果您在 class1 中的代码始终将 skip 值设置为 true,那么行为会稍微改变。如果一个线程首先执行 class1,然后执行 class2,那么两者的 skip 都将为 true。如果线程先执行 class2,然后执行 class1,则 skip 将为前者的 false 和为后者的 true。您没有证明有一种方法可以将 skip 变回 false

编辑 重新阅读您的问题。如果您实际上希望所有线程都处于完全相同的状态,那么您就不会使用 ThreadLocal。只需使用常规变量并将其标记为 volatile 或使用同步保护它。

关于java - 私有(private)静态最终实例的线程局部行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2160601/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com