54-¿Cuáles son las similitudes y diferencias entre CyclicBarrier y CountdownLatch?

Barrera cíclica
efecto

CyclicBarrier y CountDownLatch tienen ciertas similitudes. Ambos pueden bloquear uno o un grupo de subprocesos. Hasta que se cumpla una determinada condición predeterminada, estos subprocesos en espera comenzarán uniformemente y continuarán ejecutándose hacia abajo. Solo porque tienen esta similitud, podría pensar que sus funciones son exactamente las mismas, pero no lo son.

CyclicBarrier puede construir un punto de reunión.Cuando un hilo se ejecuta await (), esperará en el punto de reunión y esperará a que se revoque la valla. Hasta que el número predeterminado de hilos llegue a este punto de ensamblaje, se revocará el cerco, y los hilos que estaban en espera se pondrán en marcha en este momento y seguirán realizando el resto de tareas.

Da un ejemplo en la vida. Supongamos que nuestra clase va al parque para una excursión de primavera y alquilaremos una bicicleta para tres personas. Todos pueden montarla. Sin embargo, como esta bicicleta es para tres personas, es necesario reunir tres personas para montar una y caminar. desde la puerta del parque hasta la bicicleta, la posada tarda un rato. Luego simulamos este escenario y escribimos el siguiente código:

public class CyclicBarrierDemo {
    
    
    public static void main(String[] args) {
    
    
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        for (int i = 0; i < 6; i++) {
    
    
            new Thread(new Task(i + 1, cyclicBarrier)).start();
        }
    }
    static class Task implements Runnable {
    
    
        private int id;
        private CyclicBarrier cyclicBarrier;
        public Task(int id, CyclicBarrier cyclicBarrier) {
    
    
            this.id = id;
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
    
    
            System.out.println("同学" + id + "现在从大门出发,前往自行车驿站");
            try {
    
    
                Thread.sleep((long) (Math.random() * 10000));
                System.out.println("同学" + id + "到了自行车驿站,开始等待其他人到达");
                cyclicBarrier.await();
                System.out.println("同学" + id + "开始骑车");
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

Como puede ver en este código, primero construimos una CyclicBarrier con un parámetro de 3. El parámetro de 3 significa que debemos esperar a que 3 subprocesos alcancen este punto de ensamblaje antes de que se liberen; luego abrimos 6 en el bucle for Subproceso, el objeto Runnable ejecutado en cada subproceso se encuentra en la clase Task a continuación, y puede ver su método de ejecución directamente. Primero imprimirá "Classmate XX ahora comienza desde la puerta y va a la estación de bicicletas", y luego un tiempo Sueño, que representa el tiempo que se tarda en caminar desde la puerta hasta la estación de bicicletas, dado que la velocidad al caminar de cada estudiante es diferente, el tiempo se simula mediante un valor aleatorio.

Cuando todos los estudiantes hayan llegado a la posada, por ejemplo, cuando un cierto compañero llegue a la posada, se imprimirá el mensaje "El estudiante XX ha llegado a la posada de bicicletas y ha comenzado a esperar a que lleguen otros", y luego se imprimirá el Se llama al método await () de CyclicBarrier. Una vez que llama a este método, esperará hasta que tres personas se reúnan, y luego continuará ejecutándose. Una vez que comience a continuar ejecutándose, significa que los tres estudiantes han comenzado a montar juntos, por lo que imprime "algunos" Alguien Empecé a montar en bicicleta "esta frase.

A continuación, ejecutamos este programa, los resultados son los siguientes:

同学1现在从大门出发,前往自行车驿站
同学3现在从大门出发,前往自行车驿站
同学2现在从大门出发,前往自行车驿站
同学4现在从大门出发,前往自行车驿站
同学5现在从大门出发,前往自行车驿站
同学6现在从大门出发,前往自行车驿站
同学5到了自行车驿站,开始等待其他人到达
同学2到了自行车驿站,开始等待其他人到达
同学3到了自行车驿站,开始等待其他人到达
同学3开始骑车
同学5开始骑车
同学2开始骑车
同学6到了自行车驿站,开始等待其他人到达
同学4到了自行车驿站,开始等待其他人到达
同学1到了自行车驿站,开始等待其他人到达
同学1开始骑车
同学6开始骑车
同学4开始骑车

Puedes ver que 6 estudiantes caminaron desde la puerta hasta la estación de bicicletas uno tras otro. Debido a que la velocidad de cada uno es diferente, habrá 3 estudiantes que llegarán primero a la estación de bicicletas, pero entre los 3 estudiantes que llegaron primero, llegaron los 2 primeros. Debe esperar a que llegue la tercera persona antes de poder comenzar a conducir. Lo mismo ocurre con los estudiantes que están detrás: dado que el primer automóvil se ha retirado, el segundo automóvil todavía tiene que esperar a que tres personas se reúnan antes de poder arrancar juntos.

Para lograrlo, si no usas CyclicBarrier para hacerlo, la lógica puede ser muy complicada, porque no sabes qué compañero llegará primero y cuál llegará después. Después de usar CyclicBarrier, esta lógica se puede implementar de manera muy concisa y elegante, lo que es un escenario de aplicación muy típico.

Ejecutar acción barrera Acción

public CyclicBarrier (int Parties, Runnable fenceAction): Cuando el hilo de las partes llega al punto de reunión, esta acción se ejecutará antes de continuar ejecutándose.

A continuación, presentaremos una de sus funciones adicionales, que es realizar la función de acción barreraAcción. También hay un constructor de CyclicBarrier que pasa dos parámetros. El primer parámetro sigue siendo partes, lo que significa que se necesitan varios hilos. El segundo parámetro es un objeto Runnable, que es la barreraAction que presentaremos a continuación.

Cuando el número preestablecido de subprocesos alcance el punto de ensamblaje, ejecutarán el objeto Runnable pasado aquí cuando comiencen. Entonces supongamos que cambiamos el constructor del código justo ahora para que se vea así:

CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
    
    
    @Override
    public void run() {
    
    
        System.out.println("凑齐3人了,出发!");
    }
});

Se puede ver que hemos pasado el segundo parámetro, que es un objeto Runnable. Después de pasar este Runnable aquí, la tarea imprimirá "3 personas, ¡vamos!" Si el código anterior se cambia a este, el resultado de la ejecución es el siguiente:

同学1现在从大门出发,前往自行车驿站
同学3现在从大门出发,前往自行车驿站
同学2现在从大门出发,前往自行车驿站
同学4现在从大门出发,前往自行车驿站
同学5现在从大门出发,前往自行车驿站
同学6现在从大门出发,前往自行车驿站
同学2到了自行车驿站,开始等待其他人到达
同学4到了自行车驿站,开始等待其他人到达
同学6到了自行车驿站,开始等待其他人到达
凑齐3人了,出发!
同学6开始骑车
同学2开始骑车
同学4开始骑车
同学1到了自行车驿站,开始等待其他人到达
同学3到了自行车驿站,开始等待其他人到达
同学5到了自行车驿站,开始等待其他人到达
凑齐3人了,出发!
同学5开始骑车
同学1开始骑车
同学3开始骑车

Se puede ver que después de que tres personas formen un grupo, se imprimirá una oración como "¡Hagamos tres personas, vamos!" Esta oración es exactamente el resultado de la ejecución cuando pasamos en Runnable aquí.

Vale la pena señalar que esta declaración solo se imprime una vez por ciclo, no significa que tenga varios hilos esperando para imprimir varias veces, sino que esta tarea solo se ejecuta una vez cuando la puerta está "abierta".

Similitudes y diferencias entre CyclicBarrier y CountDownLatch

Resumamos las similitudes y diferencias entre CyclicBarrier y CountDownLatch.

El mismo punto: puede bloquear uno o un grupo de subprocesos hasta que se cumpla una determinada condición preestablecida, y luego comenzar de manera uniforme.

Pero también tienen muchas diferencias, como sigue.

  • El papel del objeto es diferente: CyclicBarrier tiene que esperar a que un número fijo de subprocesos alcance la posición de la valla para continuar la ejecución, mientras que CountDownLatch solo necesita esperar a que el número cuente hacia atrás hasta 0, es decir, CountDownLatch actúa sobre el evento, pero CyclicBarrier actúa en el hilo; CountDownLatch está llamando a countDown Después del método, el número se cuenta hacia atrás en 1, y CyclicBarrier es para disminuir el recuento en 1 después de que un hilo comienza a esperar.

  • La reutilización es diferente: CountDownLatch no se puede usar nuevamente después de que la cuenta regresiva llega a 0 y el pestillo se activa para abrirse, a menos que se cree una nueva instancia; y CyclicBarrier se puede reutilizar, como se puede ver en el código ahora, cada 3 estudiantes llegan Puede comenzar después y no es necesario que cree una nueva instancia. CyclicBarrier también puede llamar al método reset para restablecer en cualquier momento. Si algunos subprocesos ya han llamado al método await y comenzaron a esperar al restablecerse, estos subprocesos lanzarán BrokenBarrierException.

  • Diferentes acciones de ejecución: CyclicBarrier tiene una acción de ejecución barreraAction, pero CountDownLatch no tiene esta función.

Supongo que te gusta

Origin blog.csdn.net/Rinvay_Cui/article/details/111056719
Recomendado
Clasificación