Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在两组不同的任务中正确使用CyclicBarrier的循环行为?_Java_Multithreading_Concurrency_Synchronization - Fatal编程技术网

Java 如何在两组不同的任务中正确使用CyclicBarrier的循环行为?

Java 如何在两组不同的任务中正确使用CyclicBarrier的循环行为?,java,multithreading,concurrency,synchronization,Java,Multithreading,Concurrency,Synchronization,当最后一个线程进入屏障时,CyclicBarrier执行屏障操作 如果CyclicBarrier中定义了5个参与方(线程),则当第5个线程(任务)将进入屏障时,屏障将跳闸(即重置),屏障操作将被执行 在这里,第五个线程是什么类型并不重要。它可以是任何任务 因此,我的问题是: 如果有两组任务(每5个线程),那么如何确保首先执行一组特定的任务,然后执行barrier action命令。 然后执行剩余的一组任务,然后再次执行barrier action命令 CyclicBarrier是否适用于此类场景

当最后一个线程进入屏障时,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();
            }
    
        }
    
    }
    
    我期望的行为是首先执行所有验证任务,然后执行服务任务


    感谢您的帮助。

    您不需要使用大小为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