嗨,我有这样的班级定义

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/

10-12 22:30