CountDownLatch 和 CyclicBarrier 三个线程顺序输出

一、CountDownLatch

  其实要完成这种某个线程等待其他线程结果才能开始任务的业务,直接在需要准备的线程中join()依赖的线程就能完成要求,但是在博客的上一篇《三个线程顺序输出》中也说到过,join的线程返回,必须是子线程已经结束。而CountDownLatch提供了更灵活的方案,可在子线程完成好其他线程依赖的工作后调用countDown()方法主动减少计数,同时继续做线程间业务无依赖的其他工作。

  这里CountDownLatch只提供了一个构造方法,参数为大于0整数:

 public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

  具体演示如下:

public class CountDownLatchTest {

    private static CountDownLatch counter = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程:" + Thread.currentThread().getName() + " start working!");
                try {
                    Thread.sleep(2000);
                    counter.countDown();
                    System.out.println("子线程:" + Thread.currentThread().getName() + " working finish!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "thread_A");
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程:" + Thread.currentThread().getName() + " start working!");
                try {
                    Thread.sleep(1000);
                    counter.countDown();
                    System.out.println("子线程:" + Thread.currentThread().getName() + " working finish!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "thread_B");
        threadA.start();
        threadB.start();
        counter.await();
        System.out.println("A、B准备就绪!");
        // do something C...
    }
}

  结果:

  可以看到在counter.countDown()被调用两次后,主线程便继续执行,同时子线程A、B仍可继续完成各自的工作。需要注意的是,这里初始化的计数值为2,调用2次正好返回,如果初始值为3,而实际只调用2次,那么程序就会在await()处无限等待。因此await()也提供了带等待时间的使用方法:

public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

  例如把测试程序中的await()改成如下:

counter.await(1000,TimeUnit.MILLISECONDS);

  可以看到结果中,await()在没有等到计数归0,就回到主线程继续执行:

  另外CountDownLatch也提供了getCount()方法随时获取当前剩余计数。

扫描二维码关注公众号,回复: 1437825 查看本文章

  

二、CyclicBarrier

  译作同步屏障,提供了2种初始化方法,第一种为简单int参数:

public CyclicBarrier(int parties) {
        this(parties, null);
    }

  即设定要在屏障处等待的线程数,到达预定的数目后程序即可继续往下执行。

  

三、二者区别

猜你喜欢

转载自www.cnblogs.com/lyInfo/p/9131103.html