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