美文网首页
Countdownlatch与CyclicBarrier

Countdownlatch与CyclicBarrier

作者: ZMRWEGo | 来源:发表于2019-03-20 12:58 被阅读0次

    CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。 CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
    这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。

    CountDownLatch:

    package com.guozz.test.testCountDownLatchAndCyclicBarrier;
     
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
     
    /**
     * 
     * @author paul
     * 
     * CountDownLatch 很适合用来将一个任务分为n个独立的部分,等这些部分都完成后继续接下来的任务,
     * CountDownLatch 只能出发一次,计数值不能被重置。
     * 
     * 基于CountDownLatch 的模拟项目,一个项目可以分为多个模块,只有但这些模块都完成后才可以继续下一步的工作。
     * 
     * 
     *  countDown方法,当前线程调用此方法,则计数减一
        await方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
        
        executorService.shutdown() 并不是终止线程的运行,而是禁止在这个Executor中添加新的任务
         void shutdown()
            启动一个关闭命令,不再接受新任务,当所有已提交任务执行完后,就关闭。如果已经关闭,则调用没有其他作用。
            抛出:
            SecurityException - 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程
                           (因为它没有保持 RuntimePermission("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。
     */
    public class CountDownLatchTest {
        //定义计数器
        static  final int  SIZE=20;
        
        public static void main(String[] args) {
            CountDownLatch latch = new CountDownLatch(SIZE);
            Random random = new Random();
            ExecutorService executorService = Executors.newCachedThreadPool();
            //让等待所有子线程执行完毕
            Controller controller = new Controller(latch);
            executorService.execute(controller);
            
            //将SIZE个小任务去执行,多个子线程任务
            for(int i=0;i<SIZE;i++){
                executorService.execute(new Module(latch,"模块"+(i+1),random.nextInt(2000)));
            }
            executorService.shutdown();//并不是终止线程的运行,而是禁止在这个Executor中添加新的任务
        }
    }
     
     
    class Module implements Runnable{
        
        private CountDownLatch latch;
        
        private String name;
        
        private int random;
        
        public Module(CountDownLatch latch,String name,int random){
            this.latch=latch;
            this.name=name;
            this.random=random;
        }
     
        @Override
        public void run() {
            work();     
            latch.countDown(); //当前线程调用此方法,则计数减一
            
        }
     
        private void work() {
             try {
                TimeUnit.MILLISECONDS.sleep(random);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }  
               System.out.println(name + " 完成,耗时:" + random);
        }
    }
     
     
    class Controller implements Runnable{
        
        private CountDownLatch latch;
        
        public Controller(CountDownLatch latch){
            super();
            this.latch=latch;
        }
     
        @Override
        public void run() {
            try {
                latch.await();  //调用此方法会一直阻塞当前线程,直到计时器的值为0
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("所有任务都完成,任务完成");         
        }
    }
    

    CyclicBarrier

    package com.guozz.test.testCountDownLatchAndCyclicBarrier;
     
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    /**
     * 
     * @author HardPass
     * 
     * CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。
     *  在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。
     * 因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
        CyclicBarrier可以多次重复使用
     */
    public class CyclicBarrierTest_RelayRace {
     
        public static void main(String[] args) throws InterruptedException {
            
            ExecutorService exec = Executors.newCachedThreadPool();
            
            final CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() {
     
                @Override
                public void run() {
                    System.out.println("好了,大家可以去吃饭了……"  );
                }
            });     
            
            System.out.println("要吃饭,必须所有人都到终点,oK?");                
            System.out.println("不放弃不抛弃!");
            
            for (int i = 0; i < 4; i++) {
                exec.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName() + ":Go");
                        try {
                            Thread.sleep((long) (2000 * Math.random()));
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+ ":我到终点了");
                        try {
                            barrier.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (BrokenBarrierException e) {
                            e.printStackTrace();
                        }
                        
                        System.out.println(Thread.currentThread().getName()+ ":终于可以吃饭啦!");
     
                    }
                });
     
            }
            exec.shutdown();
                    
        }
        
        
     
    }
     
    

    相关文章

      网友评论

          本文标题:Countdownlatch与CyclicBarrier

          本文链接:https://www.haomeiwen.com/subject/bvczmqtx.html