Diferencia entre CountDownLatch y CyclicBarrier en Java

Aunque tanto CountDownLatch como CyclicBarrier se utilizan como una ayuda de sincronización que permite que al menos un subproceso espere, hay ciertas diferencias entre ellos. Conocer esos contrastes entre CountDownLatch y CyclicBarrier en Java lo ayudará a elegir cuándo una de estas utilidades le servirá mejor y, obviamente, también es una pregunta de consulta java decente.

CountDownLatch es un subproceso que espera que finalicen varios subprocesos o que llama a countDown(). Cuando todos los subprocesos han llamado a countDown(), el subproceso en espera continúa ejecutándose.

Ejemplo: 

Java

// Java Program to demonstrate Usage of CountDownLatch
// Its used when a thread needs to wait for other
// threads before starting its work
 
// Importing required classes
import java.util.concurrent.CountDownLatch;
 
// Main class
public class CountDownLatchDemo {
 
    // Main driver method
    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);
 
        // Creating worker threads
        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");
 
        // Starting above 4 threads
        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();
        }
    }
}
Producción

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

CyclicBarrier es cuando diferentes subprocesos se mantienen apretados entre sí (esperan el uno al otro) y cuando todos han terminado su ejecución, el resultado debe combinarse en el subproceso principal.

Ejemplo

Java

// Java program to demonstrate Execution on Cyclic Barrier
 
// Importing required classes
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
 
// Class 1
// Class implementing Runnable interface
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 2
// Implementing Runnable interface
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);
 
        // Starting the thread using start() method
        t1.start();
    }
 
    // Method
    public void run()
    {
        // Print statement
        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));
 
        // Creating object of class 1 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) {
 
            // Display exceptions along with line number
            // using printStackTrace() method
            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");
    }
}
Producción

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

Diferencia entre CountDownLatch y CyclicBarrier 

pestillo de cuenta regresiva

Barrera cíclica

CountDownLatch es una construcción que un subproceso busca mientras diferentes subprocesos cuentan en el pestillo hasta que llega a cero.  Una CyclicBarrier es una construcción reutilizable en la que un conjunto de subprocesos permanece junto hasta que aparece la totalidad de los subprocesos. Para entonces, la barrera se rompe y se puede hacer un movimiento alternativo.
CountDownLatch mantiene un recuento de tareas. CyclicBarrier mantiene un recuento de subprocesos.
En CountDownLatch, un solo subproceso puede realizar una cuenta atrás más de una vez, esto reduciría el número de veces que se llama al método countdown(). En CyclicBarrier, un solo subproceso puede llamar awaits solo una vez, lo que reduciría el recuento de barreras en uno solo, incluso si el método call awaits() más de una vez.
Cuando estamos usando un CountDownLatch, debe especificar el no. de llamadas al método countdown() al crear un objeto CountDownLatch. Cuando estamos usando CyclicBarrier, debe especificar el no. de subprocesos que deberían llamar a la función await() para activar la barrera.
Se inicializa en N y se usa para hacer que un subproceso esté en espera hasta que N strings hayan terminado alguna actividad, o alguna actividad haya terminado N veces. Si tiene un CyclicBarrier inicializado en 3, eso significa que debería tener, en cualquier caso, 3 strings para llamar await().
CountDownLatch no se puede reutilizar, cuando el conteo llega a cero, no se puede restablecer.  CyclicBarrier se puede reutilizar después de que se liberan los subprocesos de retención.
En CountDownLatch, solo el hilo actual que tiene un problema arroja un caso/excepción especial. En una CyclicBarrier, si un subproceso experimenta un problema (tiempo de espera, interrupción), la amplia gama de subprocesos que han alcanzado await() obtiene un caso/excepción especial. 
Es avanzable. No es avanzable.
Si el subproceso actual se interrumpe, arrojará InterruptedException . No afectará a otros hilos. Si un subproceso se interrumpe mientras espera, todos los demás subprocesos en espera generarán BrokenBarrierException

Publicación traducida automáticamente

Artículo escrito por tarunsinghwap7 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *