2010-01-29 55 views
2

您好我有类定义这样ThreadLocal的行为

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对于每个线程都是本地的。我在这里看到一些冲突。请帮助我。

回答

4

你的问题不是很清楚。

但我被告知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。在我的示例中,这会有不同的行为线程2将会在线程启动第二个线程时接收线程1中的值。

编辑如果您在class1中的代码始终将skip值设置为true,则行为会发生一些变化。如果线程先执行class1,那么class2然后跳过将为true。如果一个线程先执行class2然后执行class1,那么前者的skip将为false,后者则为true。您不会显示有任何方法可以跳转回false

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

+0

冲突我的意思是只有一个类的实例返回成员变量的不同值之间的冲突。 – 2010-01-29 09:05:33

+0

编辑的代码显示我如何设置跳到假。 – 2010-01-29 09:19:19

+0

如果这是你的意图,这不是冲突。 ThreadLocals用于此目的。对于新代码,由于在class1中执行的值始终设置为“true”,方法跳过,然后重置为“false”,所以事件顺序不同。使用新代码没有理由 - 只需删除class1中的代码并删除class2中的if if即可。 – 2010-01-29 09:48:13