Java getClass().getName()返回null
我正在使用testNG为我们的测试编写者提供一个“框架”,以加快测试的开发。为了实现这一点,我有一个抽象的测试类。所有的书面测试都来自这个测试类。testNG可以并行运行这些测试。现在我注意到,有时在@BeforeClass方法中,我的简单“getClass().getName()”方法在并行执行时返回nullJava getClass().getName()返回null,java,multithreading,thread-safety,testng,Java,Multithreading,Thread Safety,Testng,我正在使用testNG为我们的测试编写者提供一个“框架”,以加快测试的开发。为了实现这一点,我有一个抽象的测试类。所有的书面测试都来自这个测试类。testNG可以并行运行这些测试。现在我注意到,有时在@BeforeClass方法中,我的简单“getClass().getName()”方法在并行执行时返回null private static ThreadLocal<String> className; @BeforeClass public void init(){
private static ThreadLocal<String> className;
@BeforeClass
public void init(){
initName();
className.set(getClass().getName());
log("Starting test " + className.get());
}
private synchronized void initName(){
if(className == null){
className = new ThreadLocal<>();
}
}
一些评论:Threadlocal ClassName必须是静态的(我稍后在@Dataprovider中使用它的值)
由于它是随机发生的,并且在任何测试中都可能发生,所以我假设这是一个线程安全问题,但我不知道如何使“getClass().getName()”更线程安全
感谢您的帮助您似乎有比赛状态。如果一个线程在其他线程调用
log
之前调用initName
,则新的ThreadLocal
将没有值,即返回null
这里没有线程安全保护
initName
中的null
检查initName跳过initName
中的延迟初始化!它不是线程安全的
相反,直接初始化ThreadLocal
字段(并注意final
):
private static final ThreadLocal className=new ThreadLocal();
(顺便问一下:为什么您需要一个ThreadLocal
来保存当前类的名称?只要调用getClass().getName()
),您随时都可以轻松地获得它。我假设输入initName()的第一个线程将阻止其他线程,因为它已同步。这个假设错了吗?如果是,那么阻止其他线程的正确方法是什么?@MajorT您的initName
方法在实例上同步,而不是在类上同步,因此,在不同实例上调用的initName
将并行运行。我需要它,因为我在@dataprovider方法中动态创建数据,该方法是静态的,我需要获取该静态方法中子类的类名。我现在意识到更好的方法可能是使用testNG工厂,但现在太晚了,所以我需要一个变通方法。我现在将尝试您的“非懒惰”初始化:)之前阅读的期末考试真的做到了:)非常感谢!
...
Starting test com.mycompany.testsets.LocalTestSet$IntegrationTest3
Starting test null
Starting test com.mycompany.testsets.LocalTestSet$IntegrationTest1
...
private static final ThreadLocal<String> className = new ThreadLocal<>();