[Java Concurrency] CountDownLatch example usage scenarios



Example I CountDownLatch usage scenarios



1. A single thread blocked waiting for individual: a CountDownLatch initialization, setting its count to 1, calls await the thread A () blocks, and perform the operation in the thread B, after calling the countDown () method, Count - 1, thread A blocked released;

2. Single blocked waiting for multiple threads: a CountDownLatch initialization, setting its count to 2, calls await the thread A () occlusion; and perform the operation thread B, invoke the countDown () method, counting --1; while thread C is longer perform operations, calls the countDown () method, counting --1; threads after the implementation of operations B and C, until its count is decremented to zero, then the release thread a blocked;

3. A plurality of threads are blocked waiting for a single thread: a plurality of thread objects in the await calls CountDownLatch () method blocks, counted in the countDown another thread () is 0, the threads can be executed;

4. A plurality of threads are blocked waiting for a plurality of threads: a plurality of thread objects in the await calls CountDownLatch () method blocks, in a further counting countDown plurality of threads () is 0, the blocked threads can be executed;

5. CountDownLatch be used:

  • ① single thread threaded Wait: A thread is blocked after waiting for thread B is finished, the operation A thread of execution;
  • ② wait threaded threads: Thread A blocked, waiting threads B, C, D and other finished thread, thread A operation is performed;
  • ③ single-threaded and multi-threaded blocking each other: Thread B, C, D, are first blocked new CountDownLatch (1) live objects, thread A in the first release B, C, D are blocked, then B, C, D three thread can continue execution after the thread a is released, immediately (3) the object blocked new CountDownLatch, B, C, D after the implementation of three threads, each thread count by one, after releasing the blocking thread a, continues thread a content;
  • ④ single-threaded and multi-threaded blocking each other and set the time-out time: Based on the above ③ case of timeout wait, if B, C, D thread not been completed within the specified time, the thread A is also unblocked, continue to after the execution of the code;


II CountDownLatch simple example of thread blocks



1. Definitions: the child thread running CountDownLatch await call blocking method, a method countDown call count is decremented to zero, the child thread unblocks the main thread;

Code Example 2:

import java.util.concurrent.CountDownLatch;

/**
 * 子线程运行后调用 CountDownLatch 的 await 方法阻塞 ,
 *      在主线程中调用 countDown 方法将计数减为 0 , 子线程解除阻塞
 */
public class CountDownLatchDemo {

    public static void main(String[] args) {

        System.out.println("1. 主线程 : 开始运行 , 创建 CountDownLatch 对象初始计数为 1");

        //创建 CountDownLatch 对象 , 初始计数为 1
        CountDownLatch countDownLatch = new CountDownLatch(1);

        System.out.println("2. 主线程 : 创建子线程并运行");

        //创建子线程 , 并设置其 countDownLatch 对象, 运行子线程
        MyThread myThread = new MyThread(countDownLatch);
        myThread.start();

        System.out.println("3. 主线程 : 调用 countDownLatch.countDown() 方法");
        countDownLatch.countDown();


        System.out.println("4. 主线程 : 运行结束");
    }

    static class MyThread extends Thread{

        /**
         * 用于阻塞的 CountDownLatch 对象
         */
        CountDownLatch countDownLatch;

        /**
         * 主线程中传入 CountDownLatch 对象 , 两个线程公用一个该对象
         * @param countDownLatch
         */
        public MyThread(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            try {
                System.out.println("1. 子线程 : 开始运行 , 并调用 countDownLatch.await() 方法阻塞");

                //阻塞子线程
                countDownLatch.await();

                System.out.println("2. 子线程 : CountDownLatch 对象计数为 0 , 子线程继续运行并结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

}

3. The results:

1. 主线程 : 开始运行 , 创建 CountDownLatch 对象初始计数为 1
2. 主线程 : 创建子线程并运行
3. 主线程 : 调用 countDownLatch.countDown() 方法
1. 子线程 : 开始运行 , 并调用 countDownLatch.await() 方法阻塞
4. 主线程 : 运行结束
2. 子线程 : CountDownLatch 对象计数为 0 , 子线程继续运行并结束


III CountDownLatch multiple threads co-blocking example



1. Scenario Description: Athletes race, a referee, four players, four players first wait for the referee issuing the order, can begin to run after the referee issuing the order after waiting four players have reached the end, the announcement of the results at the end;

2. Thread model analysis:

  • ① threads: the referee is a separate thread, four athletes are four separate threads;
  • ② CountDownLatch: CountDownLatch two kinds of objects, a referee for blocking a thread, a thread for blocking athlete;
  • ③ athletes thread: a thread after four athletes running, immediately call the new CountDownLatch (1) object to block, you can not run backward;
  • After the referee to wait for a thread after thread started four athletes to perform, first call countDown four athletes thread unblocked and blocked calls await new CountDownLatch (4) objects, each athlete to the finish thread: ④ referee Thread after calling countDown method, all four players reach the end, the referee unblock, announced the results;

3. Code Example:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 情景描述 : 运动员赛跑 , 1 个裁判 , 4 个运动员 ,
 *      4 个运动员首先等待裁判发令 , 才能开始跑 ,
 *      裁判发令后在终点等待 4 个运动员都达到终点后 , 在宣布成绩 ;
 *
 * 线程模型分析 :
 *
 * ① 线程 : 裁判员是一个单独的线程 , 4 个运动员是 4 个独立的线程 ;
 * ② CountDownLatch : 两种 CountDownLatch 对象 , 一个用于阻塞裁判员线程 , 一个用于阻塞运动员线程 ;
 * ③ 运动员线程 ( 子线程 ) : 四个运动员线程一开始运行后 , 马上调用 new CountDownLatch(1) 对象阻塞住 , 不能向后运行 ;
 * ④ 裁判员线程 ( 主线程 ) : 裁判员线程要等四个运动员线程启动后才能执行 , 先调用 countDown 将四个运动员线程取消阻塞 ,
 *      然后调用new CountDownLatch(4) 对象 的 await 阻塞 , 每个运动员线程跑到终点后 ,
 *      调用 countDown 方法 , 四个运动员全部到达终点后 , 裁判员解除阻塞 , 宣布成绩 ;
 */
public class CountDownLatchDemo {

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

        //用于存储四个运动员的成绩
        int[] grades = new int[4];

        //四个运动员线程的线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        //阻塞运动员线程的倒计时锁对象 , 需要裁判员线程解锁
        CountDownLatch runnerLatch = new CountDownLatch(1);

        //阻塞裁判线程的倒计时锁对象 , 需要四个运动员线程解锁
        CountDownLatch judgeLatch = new CountDownLatch(4);

        //创建并执行运动员线程 , 使用线程池机制执行
        for(int i = 0; i < 4; i ++){
            int finalI = i;

            //创建运动员线程
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println( finalI + " 号运动员准备完毕 , 等待裁判员发令");
                        runnerLatch.await();
                        System.out.println( finalI + " 号运动员起跑");

                        //设置运动员成绩 , 这里用一个随机数代替
                        grades[finalI] = (int) (Math.random() * 10000);
                        Thread.sleep(grades[finalI]);

                        //通知裁判员到达终点
                        judgeLatch.countDown();
                        System.out.println( finalI + " 号运动员到达终点");

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };

            //使用线程池调度运行该线程
            executorService.execute(runnable);
        }


        System.out.println("裁判员 : 发令 , 起跑");

        //裁判员线程在运动员准备完毕后 , 解除上述 4 个运动员线程的阻塞 , 即运动员起跑
        runnerLatch.countDown();


        System.out.println("裁判员 : 在终点等待 4 名运动员");

        //裁判员线程阻塞, 等待 4 个运动员线程执行完毕
        judgeLatch.await();

        System.out.println("裁判员 : 运动员全部到达终点成绩为 0 号 : " + grades[0] +
                " , 1 号 : " + grades[1] +
                " , 2 号 : " + grades[2] +
                " , 3 号 : " + grades[3]);


    }



}

4. The results:

裁判员 : 发令 , 起跑
裁判员 : 在终点等待 4 名运动员
2 号运动员准备完毕 , 等待裁判员发令
2 号运动员起跑
1 号运动员准备完毕 , 等待裁判员发令
1 号运动员起跑
0 号运动员准备完毕 , 等待裁判员发令
0 号运动员起跑
3 号运动员准备完毕 , 等待裁判员发令
3 号运动员起跑
1 号运动员到达终点
2 号运动员到达终点
0 号运动员到达终点
3 号运动员到达终点
裁判员 : 运动员全部到达终点成绩为 0 号 : 5601 , 1 号 : 1763 , 2 号 : 4700 , 3 号 : 9650
Published 252 original articles · won praise 1013 · Views 1.68 million +

Guess you like

Origin blog.csdn.net/han1202012/article/details/100607549