Java 并发类 CountDownLatch CyclicBarrier Thread.Join 使用区别

 一 .CountDownLatch 

 构造函数接收一个int类型的参数作为计数器,如果想等待N个点,就传入N。当调用CountDownLatch的countDown方法时,N就会减一,直至减为零。使用await方法等待,当N的值变为零,执行await的线程继续执行。

public class DemoApplication {
    public static void main(String[] args)throws InterruptedException, ExecutionException {
        SpringApplication.run(DemoApplication.class, args);
        //1. 定义三线程的计数器
        CountDownLatch countDownLatch = new CountDownLatch(3);
        for(int index = 1;index<=3;index++){
            //2.1 执行三个子线程
            new Thread(new TaskRunnable(countDownLatch,index)).start();
        }
        //3.先执行await 方法前的 线程等所有线程都执行完(计数器为0),再执行主线程
        countDownLatch.await();
        System.out.println("最后执行主线程");

    }
}
//实现Runnable 实现 run 方法
class TaskRunnable implements Runnable{
    private CountDownLatch countDownLatch;
    private Integer index;
    public TaskRunnable(CountDownLatch countDownLatch,Integer index){
        this.countDownLatch = countDownLatch;
        this.index = index;
    }
    @Override
    public void run(){
        //2.2 每执行一个线程 ,计数器数量减一
        this.countDownLatch.countDown();
        System.out.println("第 "+this.index.toString() + "个线程,执行了。");

    }
}

 执行结果:

二.Thread.Join

 

Thread Join 主线程阻塞,等待该线程完成后再执行 主线程。
原理:利用while检查当前线程是否存活如果是一直阻塞wait(0)方法,当线程不存活,继续执行主线程。

 

public class DemoApplication {
    public static void main(String[] args)throws InterruptedException, ExecutionException {
        SpringApplication.run(DemoApplication.class, args);
        
        //Thread Join 方法 主线程阻塞,等待该线程完成后再执行 主线程。
        //线程1 和线程2 是串行的。能控制线程执行顺序
        Thread thread1 =  new Thread(new TaskJoin("thread1"));
        thread1.start();
        thread1.join();
        Thread thread2 =  new Thread(new TaskJoin("thread2"));
        thread2.start();
        thread2.join();
        System.out.println("主线程执行了!");
    }
}
class TaskJoin implements Runnable{
    private  String threadName;
    public TaskJoin(String threadName){
        this.threadName = threadName;
    }
    @Override
    public void run() {
        System.out.println(this.threadName + "子线程,执行了。");
    }
}

执行结果: 

三 CyclicBarrier [ˈsaɪklɪk][ˈbæriə(r)]

可循环使用的屏障。它要做的事情,让一组线程到达屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会打开,所有被屏障拦截的线程才会继续运行。

默认构造方法CyclicBarrier(int parties),其参数表示屏障拦截的线程数,每个线程调用await方法告诉CyclicBarrier已经到达屏障,然后当前线程阻塞。

 

public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);

        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);

        Thread thread1 =  new Thread(new TaskJoin(cyclicBarrier,"thread1"));
        thread1.start();
        Thread thread2 =  new Thread(new TaskJoin(cyclicBarrier,"thread2"));
        thread2.start();
        Thread thread3 =  new Thread(new TaskJoin(cyclicBarrier,"thread3"));
        thread3.start();
    }
}
class TaskJoin implements Runnable {
    private  String threadName;
    private CyclicBarrier cyclicBarrier;
    public TaskJoin(CyclicBarrier cyclicBarrier,String threadName){
        this.threadName = threadName;
        this.cyclicBarrier = cyclicBarrier;
    }
    @Override
    public void run() {
        System.out.println(this.threadName + "子线程,屏障点前执行了。");
        try {
            this.cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println(this.threadName + "子线程,屏障点后执行了。");
    }
}

执行结果: 

 

 总结:

 CountDownLatch:在所有线程执行完之前,阻塞的是主线程。子线程都是并行,执行完一个释放一个。但是 无法控制线程执行顺序。

Thread.Join:每个子线程都是串行的。

CyclicBarrier:所有线程未全部到达屏障点之前,线程是不释放的。

posted @ 2018-11-21 16:21  姜秋实  阅读(280)  评论(0编辑  收藏  举报