CountDownLatch

CountDownLatch was introduced in java1.5 and exists under the java.util.concurrent package.

Role: CountDownLatch This class enables a thread to wait for other threads to complete their work before executing. For example, the main thread of the application may want to execute after the thread responsible for starting the framework services has started all the framework services.

 

Implementation: CountDownLatch is implemented by a counter, and the initial value of the counter is the number of threads. Every time a thread completes its task, the value of the counter is decremented by 1. When the counter value reaches 0, it indicates that all threads have completed the task, and then the thread waiting on the latch can resume executing the task.

1.main thread start

2.create countDownLatch for n threads

3.create and start n threads

4.main thread wait on latch

5.n threads complete, tasks return

6.main thread resume execution

 

Sample is as follows:

/**

 * Case:

 * Get a batch of data and use two threads to logically process the data

 * After processing, use this batch of data to do some other things

 */

public class CountDownLunchTest1 {

    private static Random random = new Random(System.currentTimeMillis());

    private static ExecutorService executor = Executors.newFixedThreadPool(2);

    private static CountDownLatch latch = new CountDownLatch(9);

 

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

        // get the array

        int[] data = query();

        //Two threads to operate logic

        for (int i = 0; i < data.length; i++) {

            executor.execute(new SimpleRunnAble(data, i, latch));

        }

        // Ensure that all threads are executed, and then execute the following program

        latch.await();

        executor.shutdown();

        // get processed data

        System.out.println("取到数字" + Arrays.toString(data));

    }

 

    static class SimpleRunnAble implements Runnable {

        private final int[] data;

        private final int index;

        private final CountDownLatch latch;

 

        SimpleRunnAble(int[] data, int index, CountDownLatch latch) {

            this.data = data;

            this.index = index;

            this.latch = latch;

        }

 

        @Override

        public void run() {

            try {

                Thread.sleep(random.nextInt(1000));

            } catch (InterruptedException e) {

                e.printStackTrace ();

            }

 

            int value = data[index];

            if (value % 2 == 0) {

                data[index] = value * 2;

            } else {

                data[index] = value * 10;

            }

            System.out.println(Thread.currentThread().getName() + "结束");

            latch.countDown();

        }

    }

 

    private static int[] query() {

        return new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};

    }

}

 

CountDownLatch.java类中定义的构造函数:

public CountDownLatch(int count){}

 

构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值

 

与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。

 

重载的await(long timeout, TimeUnit unit)方法,提供了最大能容忍等待时间:

 

public class CountDownLunchTest2 {

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

        //new CountDownLatch(0)当为0时,latch.await()无效果

        CountDownLatch latch = new CountDownLatch(1);

        new Thread() {

            @Override

            public void run() {

                try {

                    Thread.sleep(1000);

                    latch.countDown();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }.start();

        /**

         * 最多等待10秒

         * 1.如果10秒内,没有countDown为0,10秒后发行

         * 2.如果10秒内,countDown为0,立刻发行,不用等待10秒

         */

        latch.await(10,TimeUnit.SECONDS);

        System.out.println("==========");

    }

}

 

The other N threads must refer to the latch object because they need to notify the CountDownLatch object that they have completed their respective tasks. This notification mechanism is accomplished through the  CountDownLatch.countDown() method; each time this method is called, the count value initialized in the constructor is decremented by 1. So when N threads all call this method, the value of count is equal to 0, and then the main thread can resume executing its own tasks through the await() method.

 

Usage scenarios in real-time systems:

  1.  Achieving maximum parallelism : Sometimes we want to start multiple threads at the same time to achieve maximum parallelism. For example, we want to test a singleton class. If we create a CountDownLatch with an initial count of 1, and have all threads wait on this lock, then we can easily complete the test. We only need to call the countDown() method once to allow all waiting threads to resume execution at the same time.
  2.  Waiting for n threads to complete their tasks before starting execution : For example, the application startup class ensures that all N external systems are up and running before processing user requests.
  3.  Deadlock Detection: A very convenient use case is that you can use n threads to access a shared resource, the number of threads is different in each test phase, and try to generate a deadlock.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326148430&siteId=291194637