嗨我有这样的课程定义
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
我在其他一些class1
中这样做//class1 stuff
JdbcInterceptor.getInstance().skipIntercept();
if(JdbcInterceptor.getInstance().interrupt())
{ // class1 stuff happens
}
现在我在class2中这样做
//class2 stuff
if(JdbcInterceptor.getInstance().interrupt())
{ // class2 stuff happens
}
现在我有点困惑,我知道class1会发生因为我设置了 dontIntercept ThreadLocal。我怀疑是否会发生class2的事情? 我的逻辑是我只有一个JdbcInterceptor实例,所以在对interrupt()的所有调用中都应该可以使用相同的状态。但我被告知ThreadLocals对于每个线程都是本地的。我在这看到一些冲突。请帮帮我。
答案 0 :(得分:4)
你的问题不是很清楚。
但是我被告知ThreadLocals对于每个线程都是本地的。我在这看到一些冲突。
这是对的。没有冲突。使用ThreadLocal
存储的值对象对于每个线程都是唯一的。它实际上是在内部与Thread
对象一起存储的,因此当线程终止 all 时,线程本地值也会被删除并可用于垃圾回收,除非其他线程对其进行其他引用。 / p>
如果两个类都使用相同的线程执行,那么除非您在调用之间更改本地线程的值,否则它们将具有相同的结果。如果另一个线程执行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)时,该值是当时跳过线程局部变量设置的值。
更具体地回答你的问题,然后在这个例子中:当thread1执行时,将跳过class1和class2代码。当由thread2执行时,它们不会被跳过。
请注意,还有另一种本地线程称为InheritableThreadLocal
。在我的示例中,这会有不同的行为,因为 Thread2 会在线程启动第二个线程时将值保留为 Thread1 中的值。
编辑如果class1中的代码始终将跳过值设置为true,则行为会稍微改变。如果一个线程首先执行class1,那么class2然后跳过将true
为两者。如果一个线程首先执行class2然后执行class1,那么对于前者,跳过false
,对于后者,跳过true
。您没有表明有办法将跳回到false
。
修改重新阅读您的问题。如果你实际上想要所有线程的完全相同的状态,那么你就不会使用ThreadLocal
。只需使用常规变量,并将其标记为volatile
或使用同步保护它。