CyclicBarrier在最后一个线程进入屏障时执行屏障操作。
如果在CyclicBarrier中定义了5个派对(线程),那么当第5个线程(任务)进入屏障时,屏障将跳闸(即将重置)并且屏障操作将被执行。
这里,第五个线程是什么类型并不重要。这可能是任何任务。
所以,我的问题是:
如果有两组任务(每个5个线程),那么如何确保首先执行一组特定的任务,然后执行barrier action命令。 剩下的一组任务在此之后执行,然后再次执行barrier action命令。
CyclicBarrier是否适合这些场景。 如果没有,那么它的循环行为如何在现实场景中正确使用。
以下是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();
}
}
}
上述任务的输出:
Validation Task: Thread-0 got executed
Service Task: Thread-1 got executed
Service Task: Thread-0 got executed
Service Task: Thread-4 got executed
Service Task: Thread-2 got executed
Service Task: Thread-3 got executed
Barrier action thread got executed 1 times
Validation Task: Thread-1 got executed
Validation Task: Thread-2 got executed
Validation Task: Thread-3 got executed
Validation Task: Thread-4 got executed
Barrier action thread got executed 2 times
我期望的行为是首先执行所有验证任务,然后执行服务任务。
感谢您的帮助。
答案 0 :(得分:3)
您不使用大小为5的障碍来控制10个线程。
使用大小为5的屏障来控制5个线程,其中每个线程执行一系列操作,等待所有线程完成一个步骤,然后继续下一步。
如果要启动10个线程,并让5个ServiceTask
个线程等待5 ValidationTask
个线程完成,请使用CountDownLatch
,将其同时提供给{{1} }和ValidationTask
。
ServiceTask
应该在开始时调用ServiceTask
,await()
应该在结束时调用ValidationTask
。
这样在所有countDown()
完成之前就没有ServiceTask
运行,并且ValidationTask
可以在完成后立即单独停止,而不是所有人都必须先等待停止。
答案 1 :(得分:2)
第一个问题的答案: 正如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