两个或多个线程执行完成之后继续执行之后的步骤…

2018-11-27 08:31:37来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

开发过程中或多或少会遇到一个方法需要等待两个及以上线程执行结果,如此我们如何处理,这里java提供两个方法CountDownLatch 和CyclicBarrier 方法,以下依次举例说明:

CountDownLatch 

CountDownLatch 是java.util.concurrent包下的一个方法,如下实例:

private static void testCountDownLatch() {
        //创建一个CountDownLatch,计数传入2,即等待两个线程完成计数为0后可继续执行
        //这里注意创建必须为final 否则不能调用countDown()方法
        final CountDownLatch cdl = new CountDownLatch(2);
        //线程1开始执行
        new Thread(new Runnable() {

            public void run() {
                System.out.println("线程1开始执行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1结束");
                //执行结束后计数减1
                cdl.countDown();
            }
        }).start();
        //线程1开始执行
        new Thread(new Runnable() {

            public void run() {
                System.out.println("线程2开始执行");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1结束");
                //执行结束后计数减1
                cdl.countDown();
            }
        }).start();
        try {
            //线程等待,当计数为0时,可继续执行
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("继续一下步骤");

    }

执行结果:

线程1开始执行
线程2开始执行
线程1结束
线程2结束
继续一下步骤

注意:

countDownLatch不可能重新初始化(final)或者修改CountDownLatch对象内部计数器的值(即不能再去重新计数或者添加计数)

CyclicBarrier 

CyclicBarrier 同样是java.util.concurrent包下的一个方法,如下实例:

private static void testCyclicBarrier() {
        //创建一个CyclicBarrier,计数传入3,即等待两个线程完成计数为1后可继续执行
        final CyclicBarrier cb = new CyclicBarrier(3);
        //线程1开始执行
        new Thread(new Runnable() {

            public void run() {
                System.out.println("线程1开始执行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1结束");
                //遇到屏障
                try {
                    cb.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //线程1开始执行
        new Thread(new Runnable() {

            public void run() {
                System.out.println("线程2开始执行");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2结束");
                //遇到屏障
                try {
                    cb.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        try {
            //阻塞,当计数为1时继续
            cb.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("继续一下步骤");

    }

结果:同上

注意:CyclicBarrier 传递计数要比线程多一个(这里我也不知道为啥,具体感兴趣可以看源码,大体应该为需要await()3次,每次计数减1,当计数为0时可以继续执行),提供reset()方法重置,可处理更为复杂的逻辑

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:关于操作Access数据库jdk选择问题

下一篇:SpringMVCDemo中,遇到的问题(四) 之分页功能