美文网首页
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