Java:跨多个线程共享变量
背景:我正在并行运行自动化测试。多个浏览器在相同数量的线程中启动,即1个浏览器是1个线程,使用pom.xml中的forking 下面的插件在Java:跨多个线程共享变量,java,multithreading,synchronization,atomicity,Java,Multithreading,Synchronization,Atomicity,背景:我正在并行运行自动化测试。多个浏览器在相同数量的线程中启动,即1个浏览器是1个线程,使用pom.xml中的forking 下面的插件在pom.xml中创建与线程(分叉)计数相同数量的并行**IT.class。 所有这些类同时并行执行。因此,似乎每当我创建一个可变变量或原子整数时,每个线程都会创建自己的变量,因此跨多个线程共享一个变量的概念是行不通的 <plugin> <artifactId&g
pom.xml
中创建与线程(分叉)计数相同数量的并行**IT.class
。所有这些类同时并行执行。因此,似乎每当我创建一个
可变变量
或原子整数
时,每个线程都会创建自己的变量,因此跨多个线程共享一个变量的概念是行不通的
<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>
尝试2:原子和同步
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();
}
};
AtomicInteger flag = new AtomicInteger(0);
private EventHandler<TestRunStarted> prepareTestData = event -> {
if(flag.get()==0) {
System.out.println("Preparing test data");
value.incrementAndGet();
}
AtomicInteger标志=新的AtomicInteger(0);
私有EventHandler prepareTestData=事件->{
if(flag.get()==0){
System.out.println(“准备测试数据”);
value.incrementAndGet();
}
如果您执行一个测试(flag.get()==0)和一个操作,那么您有两个方法来同步这两件事。只需将整个prepareTestData方法标记为已同步?您同步了错误的方法。您可以尝试以下方法:
volatile boolean flag = false;
public void setFlagTofalse(){
System.out.println("Inside sync block");
this.flag = true;
}
// works before class only once
private EventHandler<TestRunStarted> prepareTestData = event -> prepareData();
private synchronized void prepareData() {
if(!flag) {
System.out.println("Preparing test data");
setFlagTofalse();
}
//prepare data here
}
volatile布尔标志=false;
public void setFlagTofalse(){
System.out.println(“内部同步块”);
this.flag=true;
}
//上课前只工作一次
private EventHandler prepareTestData=event->prepareData();
私有同步的void prepareData(){
如果(!标志){
System.out.println(“准备测试数据”);
setFlagTofalse();
}
//在此准备数据
}
如果我是你,我会在访问flag变量时实现互斥锁。因此,在读取flag的值或更改其值之前,线程必须获取锁。这样,他们就不会同时读取它,也不会在读取旧值之前写入新值等
编辑:更多解释
@保罗解释了锁的作用:它基本上是一个球,可以被线抛来抛去。因此,如果你和一群人坐成一个圆圈,你就有了这个球,那么轮到你谈论“X”然后,当你完成发言时,你把球放在圆圈中间,它一直留在那里,直到同一个人或其他人再次想要球,然后等待或等待直到它可用,然后再谈论“X”。在你的情况下,一个线程必须有一个锁来改变或读取变量标志,所以你要做的是:
Mutex lock = new Mutex();
lock.aquire();
if ( flag == something ){
//do something
}
mutex.release()
或者如果您正在更改标志
lock.aquire();
flag = something;
lock.release();
正如您所见,锁是在线程之间共享的,因此它是在管理线程的类中创建的,并传递给线程中启动的可运行对象或方法
因此:
祝你好运:)标记和锁定对象必须是“静态”的,这样每个对象只有一个实例。虽然如果你有单例对象,那么你不必对标记使用“静态”,但“锁定对象”应该是静态的
另外,在“prepareTestData”中使用“lockObject”进行同步。这表明java只有一个线程在该点之外访问代码。一旦一个线程进入,其他线程将等待该线程返回再进入
private static Object lockObject = new Object();
private static Boolean flag = Boolean.FALSE;
private void prepareTestData() {
synchronized(lockObject) { //This will keep other threads waiting
if(!flag) {
//prepare data
flag = Boolean.TRUE;
}
}
}
希望这能回答你的问题。如果线程没有得到数据,它将无法通过测试。我不想这样。嘿,但是
互斥锁是我从来没有听说过的东西。如果你能分享这个片段,那将是一个很好的学习。@paul互斥锁
不过是一个锁
…你的同步已经是一个互斥锁了在对象实例中@Eugene说的是真的,但有时我更喜欢看到实际使用的锁的方法。@BasvanderLinden这是哪个api,这是import org.jruby.ext.thread.Mutex;
?@paulimport java.util.concurrent.Semaphore
,一个信号量类似于互斥锁,但你可以决定有多少线程可以访问ss锁。向下滚动到下面链接上的第2节。阅读:标志不需要是静态的。这取决于问题中未显示的上下文。而且你绝对不应该使用布尔
而不是布尔
@punit我不需要告诉其他线程像线程那样等待。睡眠或者这些线程将在ir own?他们将如何走出等待?我尝试了Sofo Gial的答案,但不起作用,可能是因为它没有静态概念。让我尝试使用静态。@MarkRotterVeel如答案中所述,如果每个线程都有自己的对象并调用准备好的数据,则标志必须是静态的。如果它是单线程,则它不是。您没有关于Boolean
@paul java负责线程的排队。如果synchronized不起作用,那么让我编辑我的答案以使用基于对象的锁定。@punitiwan。是的,这不是排队或顺序,它是并行的。所有线程都是并行运行的。谢谢,非常感谢。@paul如果这不起作用,那么你需要用这并不意味着每个线程都有自己的标志和/或自己的监视器来进行同步。@MarkRotteveel每次你发表评论时,它看起来都很有价值,但我无法理解。这次我也没有理解。@paul这表明你真的需要复习一下你的并发性和多线程知识。如果我知道为什么我会问你?如果我想温习/改进/学习我需要实施,当我们实施时,我们会陷入困境,当我们陷入困境时,我们会提出问题,当我们应该提出问题时,我们会想到可用的最佳论坛,我们就在这里。请用a更新您的问题。您对某些答案不起作用的各种评论表明某些上下文是错误的缺少。缺少什么上下文?我将尝试更新,请至少猜测一下。首先,包含这些标志和方法的类。它们是如何调用或启动的,等等。在多线程和并行执行的情况下,这是显而易见的,但让我把它放在问题描述中。这不明显,否则我不会问。所有answ
private static Object lockObject = new Object();
private static Boolean flag = Boolean.FALSE;
private void prepareTestData() {
synchronized(lockObject) { //This will keep other threads waiting
if(!flag) {
//prepare data
flag = Boolean.TRUE;
}
}
}