Java 如何在两组不同的任务中正确使用CyclicBarrier的循环行为?
当最后一个线程进入屏障时,CyclicBarrier执行屏障操作 如果CyclicBarrier中定义了5个参与方(线程),则当第5个线程(任务)将进入屏障时,屏障将跳闸(即重置),屏障操作将被执行 在这里,第五个线程是什么类型并不重要。它可以是任何任务 因此,我的问题是:Java 如何在两组不同的任务中正确使用CyclicBarrier的循环行为?,java,multithreading,concurrency,synchronization,Java,Multithreading,Concurrency,Synchronization,当最后一个线程进入屏障时,CyclicBarrier执行屏障操作 如果CyclicBarrier中定义了5个参与方(线程),则当第5个线程(任务)将进入屏障时,屏障将跳闸(即重置),屏障操作将被执行 在这里,第五个线程是什么类型并不重要。它可以是任何任务 因此,我的问题是: 如果有两组任务(每5个线程),那么如何确保首先执行一组特定的任务,然后执行barrier action命令。 然后执行剩余的一组任务,然后再次执行barrier action命令 CyclicBarrier是否适用于此类场景
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierSimpleExample {
static int barrierActionThreadCount;
public static void main(String[] args){
// 5 is the number of parties. So, when the 5th thread will enter the barrier, barrier gets tripped or reset and BarrierAction will be called.
final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new BarrierAction(barrierActionThreadCount));
for(int i=0;i<5;i++){
Thread validationTask = new Thread(new ValidationTask(i, cyclicBarrier));
validationTask.start();
}
for(int i=0;i<5;i++){
Thread serviceTask = new Thread(new ServiceTask(i, cyclicBarrier));
serviceTask.start();
}
}
}
class BarrierAction implements Runnable{
private int barrierActionThreadCount;
public BarrierAction(int barrierActionThreadCount) {
this.barrierActionThreadCount=barrierActionThreadCount;
}
// Barrier action will execute when barrier is reached i.e. number of parties waiting got executed
// In this case, it will trip when 5 different threaValidationTaskds are called and then again its number of parties will reset to 5
@Override
public void run() {
this.barrierActionThreadCount++;
System.out.println("Barrier action thread got executed "+barrierActionThreadCount+" times");
}
}
class ValidationTask implements Runnable{
CyclicBarrier cyclicBarrier;
int threadNum;
public ValidationTask(int threadNum, CyclicBarrier cyclicBarrier) {
this.threadNum = threadNum;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
Thread.sleep(threadNum*1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Validation Task: Thread-"+threadNum+" got executed");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
class ServiceTask implements Runnable{
CyclicBarrier cyclicBarrier;
int threadNum;
public ServiceTask(int threadNum, CyclicBarrier cyclicBarrier) {
this.threadNum = threadNum;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("Service Task: Thread-"+threadNum+" got executed");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
我期望的行为是首先执行所有验证任务,然后执行服务任务
感谢您的帮助。您不需要使用大小为5的屏障来控制10个线程 使用大小为5的屏障控制5个线程,其中每个线程执行一系列操作,等待所有线程完成一个步骤,然后继续下一步 如果要启动10个线程,并让5个
ServiceTask
线程等待5个ValidationTask
线程完成,则使用,将其同时提供给ValidationTask
和ServiceTask
然后,ServiceTask
应调用wait()
开始时,验证任务应调用倒计时()
在末尾
这样一来,在所有ValidationTask
完成之前,没有ServiceTask
运行,ValidationTask
可以在完成后立即停止,而不必在停止前互相等待。回答第一个问题:
正如Andreas提到的,CountDownlatch可以在您提到的场景中使用
第二个问题的答复:
下面是使用CyclicBarrier的循环行为的代码
在本例中,5个线程使用CyclicBarrier并多次调用await()方法到达多个检查点并同时等待
package dev.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBehaviorDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
public void run() {
System.out.println("All threads Arrived at barrier Checkpoint");
}
});
Thread t1= new Thread(new Task(barrier),"thread-1");
Thread t2= new Thread(new Task(barrier),"thread-2");
Thread t3= new Thread(new Task(barrier),"thread-3");
Thread t4= new Thread(new Task(barrier),"thread-4");
Thread t5= new Thread(new Task(barrier),"thread-5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
class Task implements Runnable {
CyclicBarrier barrier;
Task(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " has started for checkpoint 1");
barrier.await();
System.out.println(Thread.currentThread().getName() + " has started for checkpoint 2");
barrier.await();
System.out.println(Thread.currentThread().getName() + " has started for checkpoint 3");
barrier.await();
System.out.println(Thread.currentThread().getName() + "has finished");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
上述程序的输出为
thread-2 has started for checkpoint 1
thread-4 has started for checkpoint 1
thread-1 has started for checkpoint 1
thread-3 has started for checkpoint 1
thread-5 has started for checkpoint 1
All threads Arrived at barrier Checkpoint
thread-2 has started for checkpoint 2
thread-4 has started for checkpoint 2
thread-5 has started for checkpoint 2
thread-1 has started for checkpoint 2
thread-3 has started for checkpoint 2
All threads Arrived at barrier Checkpoint
thread-3 has started for checkpoint 3
thread-2 has started for checkpoint 3
thread-4 has started for checkpoint 3
thread-5 has started for checkpoint 3
thread-1 has started for checkpoint 3
All threads Arrived at barrier Checkpoint
thread-1has finished
thread-3has finished
thread-2has finished
thread-4has finished
thread-5has finished
谢谢,@Andreas-使用倒计时锁存器非常好,但实际上我正在尝试模拟CyclicBarrier的循环行为。假设,在现实世界的示例中,如果当前场景中提供了多组任务,而不是2组任务,那么每次我需要创建一个包含5个计数的锁存器,并调用您提到的wait()函数。但是,如何在真实场景中重复使用自行车承运人的障碍呢。CyclicBarrier over CountDownLatch的意义是什么?您正在为每个“任务”创建一个新线程。您真正需要的只是5个线程,每个线程按顺序完成一系列任务。因此,线程代码类似于
runTask1();障碍。等待();runTask2();障碍。等待();runTask3();障碍。等待()代码>。这样,所有5个线程都将在任何一个线程启动任务2之前完成任务1,所有线程都将在任何一个线程启动任务3之前完成任务2。这只使用了5个线程和1个屏障,而不是您尝试使用的15个线程,其中10个线程始终处于休眠状态。@Andreas-同意,但在CyclicBarrier中,barrier.await()在从主线程开始的参与方(线程)中调用,而不是在CountDownLatch中在主线程中调用。这里,触发点是跳闸,一旦跳闸,执行的动作是动作屏障。我能想到的实现方法是:我们需要在BarrierAction中定义runTask2()。但为了确保在runTask1()和runTask2()之后执行runTask3(),我们需要在BarrierAction中创建另一个CyclicBarrier对象,并在另一个BarrierAction中定义runTask3()。@SKumar抱歉,根本没有这样做。主线程既不使用CyclicBarrier也不使用CountDownLatch。只有辅助线程使用它们。--如果任务3在任务2完成之前无法运行,而任务2在任务1完成之前无法运行,则暗示任务3在任务1完成之前无法运行。任务1和任务3之间不需要明确的规则。@Andreas-很抱歉回复得太晚。只是挂断了与其他作品,也需要时间来探索更多关于它。我只想在这里声明,如果在主线程中创建CyclicBarrier对象,那么在工作线程屏障中调用.await(),与CountDownLatch相反,在所有线程执行开始后,在主线程中调用latch.await()函数。在浏览信号量时,刚刚发表了一篇有趣的文章,介绍了CountDownLatch、CyclicBarrier和信号量之间的区别。希望与大家分享:
thread-2 has started for checkpoint 1
thread-4 has started for checkpoint 1
thread-1 has started for checkpoint 1
thread-3 has started for checkpoint 1
thread-5 has started for checkpoint 1
All threads Arrived at barrier Checkpoint
thread-2 has started for checkpoint 2
thread-4 has started for checkpoint 2
thread-5 has started for checkpoint 2
thread-1 has started for checkpoint 2
thread-3 has started for checkpoint 2
All threads Arrived at barrier Checkpoint
thread-3 has started for checkpoint 3
thread-2 has started for checkpoint 3
thread-4 has started for checkpoint 3
thread-5 has started for checkpoint 3
thread-1 has started for checkpoint 3
All threads Arrived at barrier Checkpoint
thread-1has finished
thread-3has finished
thread-2has finished
thread-4has finished
thread-5has finished