The JUC series of Java interviews: CyclicBarrier and CountDownLatch

CyclicBarrier

concept

Contrary to CountDownLatch, you need to gather seven dragon balls to summon the dragon. That is to add, start with 0, and execute when it reaches a certain value

CyclicBarrier literally means a cyclic barrier (Barrier). What it requires is that a group of threads are blocked when they reach a barrier (also called a synchronization point). The barrier will not open until the last thread reaches the barrier, and all threads intercepted by the barrier will continue to work. The thread enters the barrier through the await method of CyclicBarrier

Case study

Collect 7 dragon balls to summon the demo of Shenlong, we need to create CyclicBarrier first

/**
* 定义一个循环屏障,参数1:需要累加的值,参数2 需要执行的方法
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
    
    
	System.out.println("召唤神龙");
});

Then write seven threads at the same time for Dragon Ball collection, but when one thread is collected, we need to let him execute the await method, wait until all the 7 threads are executed, we execute the originally defined method

        for (int i = 0; i < 7; i++) {
    
    
            final Integer tempInt = i;
            new Thread(() -> {
    
    
                System.out.println(Thread.currentThread().getName() + "\t 收集到 第" + tempInt + "颗龙珠");

                try {
    
    
                    // 先到的被阻塞,等全部线程完成后,才能执行方法
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
    
    
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }

Complete code

/**
 * CyclicBarrier循环屏障
 *
 */
public class CyclicBarrierDemo {
    
    


    public static void main(String[] args) {
    
    
        /**
         * 定义一个循环屏障,参数1:需要累加的值,参数2 需要执行的方法
         */
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
    
    
            System.out.println("召唤神龙");
        });

        for (int i = 0; i < 7; i++) {
    
    
            final Integer tempInt = i;
            new Thread(() -> {
    
    
                System.out.println(Thread.currentThread().getName() + "\t 收集到 第" + tempInt + "颗龙珠");

                try {
    
    
                    // 先到的被阻塞,等全部线程完成后,才能执行方法
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
    
    
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}

CountDownLatch

concept

Let some threads block until other threads complete a series of operations before being awakened

CountDownLatch mainly has two methods. When one or more threads call the await method, the calling thread will be blocked. When other threads call the CountDown method, the counter will be decremented by 1 (the thread calling the CountDown method will not be blocked). When the value of the counter becomes zero, the thread blocked by calling the await method will be awakened and continue execution

Scenes

Now there is such a scene, suppose there are 7 people in a study room, one of them is the monitor. The main responsibility of the monitor is to turn off the lights, lock the classroom door, and then leave after the other 6 students have left. Therefore, the monitor needs to leave. The last one to go, so is there any way to control the monitor that this thread is the last one to execute, while other threads are executed randomly

solution

At this time, CountDownLatch is used, the counter. We create a total of 6 threads, and then the value of the counter is also set to 6

// 计数器
CountDownLatch countDownLatch = new CountDownLatch(6);

Then every time the student thread is executed, the value of the counter is decreased by 1

for (int i = 0; i <= 6; i++) {
    
    
    new Thread(() -> {
    
    
        System.out.println(Thread.currentThread().getName() + "\t 上完自习,离开教室");
        countDownLatch.countDown();
    }, String.valueOf(i)).start();
}

Finally, we need to control the execution of the monitor's main thread through the await method of CountDownLatch. Here countDownLatch.await() can be thought of as a wall. Only when the counter value is 0, the wall will disappear and the main thread can continue to go down. carried out

countDownLatch.await();

System.out.println(Thread.currentThread().getName() + "\t 班长最后关门");

Without the execution result of CountDownLatch, we find that the main thread has been executed ahead of time

1	 上完自习,离开教室
0	 上完自习,离开教室
main	 班长最后关门
2	 上完自习,离开教室
3	 上完自习,离开教室
4	 上完自习,离开教室
5	 上完自习,离开教室
6	 上完自习,离开教室

After introducing the execution result of CountDownLatch, we can control the execution of the main method, so as to ensure the execution of the prerequisite tasks

0	 上完自习,离开教室
2	 上完自习,离开教室
4	 上完自习,离开教室
1	 上完自习,离开教室
5	 上完自习,离开教室
6	 上完自习,离开教室
3	 上完自习,离开教室
main	 班长最后关门

Complete code

package com.moxi.interview.study.thread;

import java.util.concurrent.CountDownLatch;


public class CountDownLatchDemo {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    

        // 计数器
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 0; i <= 6; i++) {
    
    
            new Thread(() -> {
    
    
                System.out.println(Thread.currentThread().getName() + "\t 上完自习,离开教室");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }

        countDownLatch.await();

        System.out.println(Thread.currentThread().getName() + "\t 班长最后关门");
    }
}

Guess you like

Origin blog.csdn.net/weixin_43314519/article/details/110280596