如何确保在java并行处理中一个代码块只由一个线程执行
我有一个使用maven命令行运行的测试类,如下所示:如何确保在java并行处理中一个代码块只由一个线程执行,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,我有一个使用maven命令行运行的测试类,如下所示: public class TestRunner { @org.junit.Test public void testParallel() throws InterruptedException, ExecutionException { //Takes 5 mins. Has 20 different tests with the tag @e2eDTC Results DTC = R
public class TestRunner {
@org.junit.Test
public void testParallel() throws InterruptedException, ExecutionException {
//Takes 5 mins. Has 20 different tests with the tag @e2eDTC
Results DTC = Runner.path("classpath:").tags("@e2eDTC").reportDir("target/cucumber-html-
reports").parallel(1);
assertTrue(DTC.getErrorMessages(), DTC.getFailCount() == 0);
generateReport(DTC.getReportDir());
// Takes 4 min. Has 25 different tests the tag @e2eWNG
Results WNG = Runner.path("classpath:").tags("@e2eWNG").reportDir("target/cucumber-html-
reports").parallel(1);
assertTrue(WNG.getErrorMessages(), WNG.getFailCount() == 0);
generateReport(WNG.getReportDir());
// Takes 3 min. Has 18 different tests with the tag @e2eFFD
Results FFD = Runner.path("classpath:").tags("@e2eFFD").reportDir("target/cucumber-html-
reports").parallel(1);
assertTrue(FFD.getErrorMessages(), FFD.getFailCount() == 0);
generateReport(FFD.getReportDir());
}
}
上述代码显然是连续的,需要12分钟多一点。我希望引入并行性,这样每个带有3行Results对象、断言和生成或报告的代码块(带有特定标记)都由单个线程并行运行。因此,从理论上讲,整个处理时间将略多于5分钟。这意味着带有DTC的块在一个线程上运行,WNG块在不同的线程上运行,FFD块在不同的线程上运行。在每个块中,只有一条螺纹是可以的
我尝试使用Executor服务,下面是代码
public class TestRunner {
@org.junit.Test
public void testParallel() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
Results DTC = Runner.path("classpath:").tags("@e2eDTC").reportDir("target/cucumber-html-reports").parallel(1);
assertTrue(DTC.getErrorMessages(), DTC.getFailCount() == 0);
generateReport(DTC.getReportDir());
return "DTC Success";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
Results WNG = Runner.path("classpath:").tags("@e2eWarnings").reportDir("target/cucumber-html-reports").parallel(1);
assertTrue(WNG.getErrorMessages(), WNG.getFailCount() == 0);
generateReport(WNG.getReportDir());
return "WNG Success";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
Results FFD = Runner.path("classpath:").tags("@e2eFFD").reportDir("target/cucumber-html-reports").parallel(1);
assertTrue(FFD.getErrorMessages(), FFD.getFailCount() == 0);
generateReport(FFD.getReportDir());
return "FFD Success";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
executorService.shutdown();
}
到
使它再次成为一个顺序程序。
我希望线程1被分配给标记@e2eDTC,并仅使用该标记运行测试,方式与线程2到@e2eWNG和线程3到@e2eFFD相同。有可能有这样的设置吗?我不是一个java开发人员,因此我寻求一些关于如何实现这一点的建议。这里也没有main()方法 哈希集不是线程安全的。您可以使用创建同步集
Set<Callable<String>> callables = Collections.synchronizedSet(new HashSet<Callable<String>>());
您的解决方案非常有用,性能非常好。然而,有时我确实会遇到一些随机故障。这是意料之中的吗?@Pakira非常感谢你。这看起来非常干净,非常像您的解决方案。我面临的问题是,它有调用它的主要方法。由于我正在使用maven test命令来运行此文件,因此include main method会给我以下错误
Tests in error:initializationError(eCare.ThreadTest):method main()不应该是静态initializationError(eCare.ThreadTest):Method main应该没有参数
如果我将main重命名为另一个方法名,如public void testParallel()抛出InterruptedException{
它根本不执行测试。看起来像是一个我现在可能缺少的琐碎问题@pakirathanking@Pakira。它看起来不像是重写和执行run()方法。我打印了调试结果,但似乎根本没有进入run()方法执行。有什么想法吗?我也在寻找更多信息。将start()更改为run(),似乎可以工作。有一些问题,但它似乎对我有效。请阅读以下内容:出于各种原因,start()不工作,但run()可以工作是的。我会深入挖掘并将我的发现留在这里。谢谢你的帮助@Pakira
ExecutorService executorService = Executors.newSingleThreadExecutor()
Set<Callable<String>> callables = Collections.synchronizedSet(new HashSet<Callable<String>>());
List<Callable<String>> tasksList = new ArrayList<Callable<String>>();
public class ThreadTest {
@org.junit.Test
public void testFunc() {
ThreadTest test = new ThreadTest();
Thread a = new Thread(test.new DTC());
Thread b = new Thread(test.new WNG());
Thread c = new Thread(test.new FFD());
a.start();
b.start();
c.start();
}
class DTC implements Runnable {
@Override
public void run() {
try {
// Your logic
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("DTC Success " + Thread.currentThread().getName());
}
}
class WNG implements Runnable {
@Override
public void run() {
try {
// Your logic
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("WNG Success "+ Thread.currentThread().getName());
}
}
class FFD implements Runnable {
@Override
public void run() {
try {
// Your logic
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("FFD Success "+ Thread.currentThread().getName());
}
}
}