背景:我正在并行运行自动化测试。多个浏览器以相同数量的线程启动,即 1 个浏览器是 1 个线程,在 pom.xml 中使用 fork 。
以下插件位于 pom.xml
创建相同数量的Parallel**IT.class
作为线程(fork)计数。
所有这些类都是同时并行执行的。所以,似乎每当我创建 volatile variable
时或AtomicInteger
每个线程都会创建自己的变量,因此跨多个线程共享变量的概念不起作用。
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven.failsafe.plugin}</version>
<configuration>
<systemPropertyVariables>
<webdriver.base.url>${webdriver.base.url}</webdriver.base.url>
</systemPropertyVariables>
<argLine>
-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
<forkCount>5</forkCount>
<reuseForks>true</reuseForks>
<includes>
<include>**/Parallel*IT.class</include>
</includes>
<perCoreThreadCount>true</perCoreThreadCount>
<properties>
<property>
<name>listener</name>
<value>ru.yandex.qatools.allure.junit.AllureRunListener</value>
</property>
</properties>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
我只希望 1 个线程访问“准备测试数据”功能并设置 flag
至false
,当其他线程看到flag
时如false
他们不会尝试准备测试数据。
我正在学习教程 https://www.youtube.com/watch?v=WH5UvQJizH0实现synchronization
使用volatile
多变的。也许我犯了一些错误,但所有线程都在打印 System.out.println("Preparing test data");
尝试1: volatile 和同步
volatile boolean flag = false;
public synchronized void setFlagTofalse(){
System.out.println("Inside sync block");
this.flag = true;
}
// works before class only once
private EventHandler<TestRunStarted> prepareTestData = event -> {
if(flag==false) {
System.out.println("Preparing test data");
setFlagTofalse();
}
};
尝试 2:原子和同步
AtomicInteger flag = new AtomicInteger(0);
private EventHandler<TestRunStarted> prepareTestData = event -> {
if(flag.get()==0) {
System.out.println("Preparing test data");
value.incrementAndGet();
}
最佳答案
如果我是你,我会在访问标志变量时实现互斥锁。因此,在读取标志的值或更改其值之前,线程必须获取锁。这样,他们就不会同时读取它,也不会在读取旧值时写入新值,等等。
编辑:更多说明
@paul 解释一下锁的作用:它基本上是一个可以被线程抛掷的球。因此,如果你和一群人围坐一圈,并且你有球,那么就轮到你谈论“X”了。然后,一旦你说完,你就把球放在圆圈的中间,它会一直留在那里,直到同一个人或其他人再次想要球并拿走它,或者等到它可用,然后可以谈论“X”。在您的情况下,线程必须拥有锁才能更改或读取变量标志,因此您要做的是:
Mutex lock = new Mutex();
lock.aquire();
if ( flag == something ){
//do something
}
mutex.release()
或者如果您要更改标志。
lock.aquire();
flag = something;
lock.release();
正如您所看到的,锁是在线程之间共享的。因此它是在管理线程的类中创建的,并传递给线程中启动的可运行对象或方法。
所以:
Mutex lock = new Mutex();
Runnable1 r1 = new Runnable1(lock);
Runnable2 r2 = new Runnable2(lock);
//use the lock in the methods of t1 and t2 that use your volitile var
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
//the join wait for completion of the runnable method in your class.
t1.join();
t2.join();
祝你好运:)
关于Java:在多个线程之间共享变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56273532/