📜  JavaCountDownLatch和CyclicBarrier的区别

📅  最后修改于: 2021-09-13 02:48:46             🧑  作者: Mango

尽管 CountDownLatch 和 CyclicBarrier 都被用作同步帮助,允许至少一个线程等待,但它们之间确实存在对比。了解JavaCountDownLatch 和 CyclicBarrier 之间的那些对比将帮助您选择这些实用程序中的一个何时可以更好地为您服务,显然这也是一个不错的Java查询问题。

CountDownLatch是一个等待多个线程完成或调用 countDown() 的线程。当所有线程都调用了 countDown() 后,等待的线程继续执行。

例子:

Java
// Java Program to demonstrate how
// to use CountDownLatch, Its used
// when a thread needs to wait for other
// threads before starting its work.
import java.util.concurrent.CountDownLatch;
  
public class CountDownLatchDemo {
    public static void main(String args[])
        throws InterruptedException
    {
        // Let us create task that is going to
        // wait for four threads before it starts
        CountDownLatch latch = new CountDownLatch(4);
  
        // Let us create four worker
        // threads and start them.
        Worker first = new Worker(1000, latch, "WORKER-1");
        Worker second = new Worker(2000, latch, "WORKER-2");
        Worker third = new Worker(3000, latch, "WORKER-3");
        Worker fourth = new Worker(4000, latch, "WORKER-4");
        first.start();
        second.start();
        third.start();
        fourth.start();
  
        // The main task waits for four threads
        latch.await();
  
        // Main thread has started
        System.out.println(Thread.currentThread().getName()
                           + " has finished");
    }
}
  
// A class to represent threads for which
// the main thread waits.
class Worker extends Thread {
    private int delay;
    private CountDownLatch latch;
  
    public Worker(int delay, CountDownLatch latch,
                  String name)
    {
        super(name);
        this.delay = delay;
        this.latch = latch;
    }
  
    @Override public void run()
    {
        try {
            Thread.sleep(delay);
            latch.countDown();
            System.out.println(
                Thread.currentThread().getName()
                + " finished");
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


Java
// Java program to demonstrate 
// execution on Cyclic Barrier
  
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
  
class Computation1 implements Runnable {
    public static int product = 0;
    public void run()
    {
        product = 2 * 3;
        try {
              // thread1 awaits for other threads
            Tester.newBarrier.await();
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
  
class Computation2 implements Runnable {
    public static int sum = 0;
    public void run()
    {
        // check if newBarrier is broken or not
        System.out.println("Is the barrier broken? - "
                           + Tester.newBarrier.isBroken());
        sum = 10 + 20;
        try {
            Tester.newBarrier.await(3000,
                                    TimeUnit.MILLISECONDS);
  
            // number of parties waiting at the barrier
            System.out.println(
                "Number of parties waiting at the barrier "
                + "at this point = "
                + Tester.newBarrier.getNumberWaiting());
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
        catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}
  
public class Tester implements Runnable {
    
      // create a static CyclicBarrier instance
    public static CyclicBarrier newBarrier
        = new CyclicBarrier(3);
  
    public static void main(String[] args)
    {
        // parent thread
        Tester test = new Tester();
  
        Thread t1 = new Thread(test);
            
          // start the thread
        t1.start();
    }
    public void run()
    {
        System.out.println(
            "Number of parties required to trip the barrier = "
            + newBarrier.getParties());
        System.out.println(
            "Sum of product and sum = "
            + (Computation1.product + Computation2.sum));
  
        // objects on which the child thread has to run
        Computation1 comp1 = new Computation1();
        Computation2 comp2 = new Computation2();
  
        // creation of child thread
        Thread t1 = new Thread(comp1);
        Thread t2 = new Thread(comp2);
  
        // moving child thread to runnable state
        t1.start();
        t2.start();
  
        try {
              // parent thread awaits
            Tester.newBarrier.await();
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
  
        // barrier breaks as the number of thread waiting
        // for the barrier at this point = 3
        System.out.println(
            "Sum of product and sum = "
            + (Computation1.product + Computation2.sum));
  
        // Resetting the newBarrier
        newBarrier.reset();
        System.out.println("Barrier reset successful");
    }
}


输出
WORKER-1 finished
WORKER-2 finished
WORKER-3 finished
WORKER-4 finished
main has finished

CyclicBarrier是不同线程相互挂起(互相等待),当所有线程都执行完毕后,需要在父线程中合并结果。

例子:

Java

// Java program to demonstrate 
// execution on Cyclic Barrier
  
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
  
class Computation1 implements Runnable {
    public static int product = 0;
    public void run()
    {
        product = 2 * 3;
        try {
              // thread1 awaits for other threads
            Tester.newBarrier.await();
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
  
class Computation2 implements Runnable {
    public static int sum = 0;
    public void run()
    {
        // check if newBarrier is broken or not
        System.out.println("Is the barrier broken? - "
                           + Tester.newBarrier.isBroken());
        sum = 10 + 20;
        try {
            Tester.newBarrier.await(3000,
                                    TimeUnit.MILLISECONDS);
  
            // number of parties waiting at the barrier
            System.out.println(
                "Number of parties waiting at the barrier "
                + "at this point = "
                + Tester.newBarrier.getNumberWaiting());
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
        catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}
  
public class Tester implements Runnable {
    
      // create a static CyclicBarrier instance
    public static CyclicBarrier newBarrier
        = new CyclicBarrier(3);
  
    public static void main(String[] args)
    {
        // parent thread
        Tester test = new Tester();
  
        Thread t1 = new Thread(test);
            
          // start the thread
        t1.start();
    }
    public void run()
    {
        System.out.println(
            "Number of parties required to trip the barrier = "
            + newBarrier.getParties());
        System.out.println(
            "Sum of product and sum = "
            + (Computation1.product + Computation2.sum));
  
        // objects on which the child thread has to run
        Computation1 comp1 = new Computation1();
        Computation2 comp2 = new Computation2();
  
        // creation of child thread
        Thread t1 = new Thread(comp1);
        Thread t2 = new Thread(comp2);
  
        // moving child thread to runnable state
        t1.start();
        t2.start();
  
        try {
              // parent thread awaits
            Tester.newBarrier.await();
        }
        catch (InterruptedException
               | BrokenBarrierException e) {
            e.printStackTrace();
        }
  
        // barrier breaks as the number of thread waiting
        // for the barrier at this point = 3
        System.out.println(
            "Sum of product and sum = "
            + (Computation1.product + Computation2.sum));
  
        // Resetting the newBarrier
        newBarrier.reset();
        System.out.println("Barrier reset successful");
    }
}
输出
Number of parties required to trip the barrier = 3
Sum of product and sum = 0
Is the barrier broken? - false
Number of parties waiting at the barrier at this point = 0
Sum of product and sum = 36
Barrier reset successful

CountDownLatch 和 CyclicBarrier 的区别

CountDownLatch

CyclicBarrier

CountDownLatch is a construct that a thread looks out for while different threads tally down on the latch until it arrives at zero.  A CyclicBarrier is a reusable construct where a gathering of threads stands by together until the entirety of the threads shows up. By then, the barrier is broken and a move can alternatively be made.
CountDownLatch keeps up a count of tasks. CyclicBarrier keeps up a count of threads.
When we are using a CountDownLatch, you must specify the no. of calls to the countdown() method while creating a CountDownLatch object. When we are using CyclicBarrier, you must specify the no. of threads that should call await() function to trip the barrier.
It is initialized to N used to make one thread stand by until N strings have finished some activity, or some activity has been finished N times. If you have a CyclicBarrier initialized to 3 that implies you ought to have in any event 3 strings to call await().
CountDownLatch cannot be reused, when count arrives at zero it can’t be reset.  CyclicBarrier can be reused after holding threads are released.
In CountDownLatch just the current thread that has an issue throws a special case/exception. In a CyclicBarrier, if a thread experiences an issue (timeout, interruption), the wide range of various threads that have reached await() get a special case/exception. 
It’s advanceable. It’s not advanceable.
If the current thread is interrupted, it will throw InterruptedException. It will not impact other threads. If one thread is interrupted while waiting then all other waiting threads will throw BrokenBarrierException