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(); } } }
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"); } }
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