countDownLatch使用説明-転送

16542 ワード

文書ディレクトリ

  • 1.背景:
  • 2.コンセプト
  • 3.ソース
  • 4.例
  • 一般例:
  • アナログ同時例:
  • 自問自答コーナー
  • 回転:https://www.jianshu.com/p/e233bb37d2e6

    1.背景:


    countDownLatchはjava 1です.5は導入され、それとともに導入されたツールクラスにはCyclicBarrier、Semaphore、concurrentHashMap、BlockingQueueがある.Javaに存在する.util.cucurrentパッケージ.

    2.概念


    countDownLatchこのクラスでは、1つのスレッドが他のスレッドがそれぞれ実行されるのを待ってから実行されます.カウンタの初期値はスレッドの数であるカウンタによって実現される.1つのスレッドが実行されるたびにカウンタの値は-1になり、カウンタの値が0の場合、すべてのスレッドが実行されたことを示し、ロックで待機していたスレッドが動作を再開することができます.

    3.ソース


    countDownLatchクラスには、//パラメータcountがカウント値public CountDownLatch(int count){};クラスには、//await()メソッドを呼び出すスレッドが保留され、count値が0になるまでpublic void await()throws InterruptedException{};//await()と似ていますが、一定時間待ってからcount値が0になっていないとpublic boolean await(long timeout,TimeUnit unit)throws InterruptedException{};//count値を1 public void countDown()に減算します.

    4.例


    一般的な例:

    , , 。
    public class CountDownLatchTest {
    
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);
        System.out.println(" …… ……");
        // 
        ExecutorService es1 = Executors.newSingleThreadExecutor();
        es1.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println(" :"+Thread.currentThread().getName()+" ");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            }
        });
        es1.shutdown();
    
        // 
        ExecutorService es2 = Executors.newSingleThreadExecutor();
        es2.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(" :"+Thread.currentThread().getName()+" ");
                latch.countDown();
            }
        });
        es2.shutdown();
        System.out.println(" …… ……");
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(" , ");
    }
    

    }結果セット:
     …… ……
     …… ……
     :pool-1-thread-1 
     :pool-2-thread-1 
     , 
    

    シミュレーションの同時実行例:

    public class Parallellimit {
        public static void main(String[] args) {
            ExecutorService pool = Executors.newCachedThreadPool();
            CountDownLatch cdl = new CountDownLatch(100);
            for (int i = 0; i < 100; i++) {
                CountRunnable runnable = new CountRunnable(cdl);
                pool.execute(runnable);
            }
        }
    }
    
     class CountRunnable implements Runnable {
        private CountDownLatch countDownLatch;
        public CountRunnable(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
        @Override
        public void run() {
            try {
                synchronized (countDownLatch) {
                    /***  */
                    countDownLatch.countDown();
                    System.out.println("thread counts = " + (countDownLatch.getCount()));
                }
                countDownLatch.await();
                System.out.println("concurrency counts = " + (100 - countDownLatch.getCount()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    修正後のコード:
    package juc;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CountDownLatchParallellimit {
        public static void main(String[] args) throws InterruptedException {
            ExecutorService pool = Executors.newCachedThreadPool();
            CountDownLatch cdl = new CountDownLatch(100);
            for (int i = 0; i < 100; i++) {
                CountRunnable runnable = new CountRunnable(cdl);
                pool.execute(runnable);
            }
            cdl.await();
            System.out.println("concurrency counts = " + (100 - cdl.getCount()));
            pool.shutdown();
    
        }
    
        static class CountRunnable implements Runnable {
            private CountDownLatch countDownLatch;
            public CountRunnable(CountDownLatch countDownLatch) {
                this.countDownLatch = countDownLatch;
            }
            public void run() {
                    synchronized (countDownLatch) {
                        /***  */
                        countDownLatch.countDown();
                        System.out.println("thread counts = " + (countDownLatch.getCount()));
                    }
            }
        }
    }
    

    説明:上のコードのsynchronizedの使い方は少しおかしいですが、CountDownLatchはスレッドが安全なCASアルゴリズムを採用しており、countDown()の後ろにgetCount()を印刷するのはパラドックスです.countDown()はスレッドボディが完了した後に実行されますが、後で文が印刷されます.
    synchronizedを加えるとスレッドが順番に印刷されます.

    自問自答コーナー


    countDown()メソッドはどこに追加されますか?CountDownLatchのcountDown()メソッドは、スレッド内のビジネス処理が完了した後に最後のセグメントに追加する必要があります.
    もし業務に異常が発生したらどうしますか?取得例外はfinallyでcountDown()を実行します.そうしないと、プライマリ・スレッドがブロックされます.
    package juc;
    
    import java.util.concurrent.CountDownLatch;
    
    public class CountDownLatchStudy {
    
        public static void main(String[] args) {
            final  int SIZE = 10;
    
            final CountDownLatch  cdl = new CountDownLatch(SIZE);
            for(int i=0;i < SIZE; i++){
                new Thread(new Runnable() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                        try {
                            Thread.sleep(100);
                            int a = 1/0;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }finally {
                            // 
                            // 
                            cdl.countDown();
                        }
                        //System.out.println(Thread.currentThread().getName()+" : "+cdl.getCount());
                    }
                }).start();
            }
            System.out.println(Thread.currentThread().getName()+" : "+cdl.getCount());
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("done");
        }
    }
    
    

    あるスレッドcountDown()が完了していない場合、getCountは0ではありません.メインスレッドはどうなりますか?メインスレッドはずっとブロックされます.
    *CountDownLatchとCyclicBarrierの違い:1.countDownLatchはカウンタで、スレッドは1つの記録を完成し、カウンタは1回しか使用できない.CyclicBarrierのカウンタはバルブのようなもので、すべてのスレッドが到着し、実行を続行する必要があります.カウンタは増加し、reset機能を提供し、複数回使用できます.
    countDownLatchクラスにはコンストラクタが1つしかありません.https://www.jianshu.com/p/e233bb37d2e6
    https://www.cnblogs.com/Lee_xy_z/p/10470181.html