CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.
区别:
1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。
2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。
3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier 唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。
应用场景:
CountDownLatch:异步转同步,,,
CyclicBarrier:批量多线程汇总,像短时间跑批类的,
总结:
CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。
package test;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
/**
 * CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.<br>
 *
 * 区别:<br>
 * 1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。<br>
 * 2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。<br>
 * 3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。<br>
 * 
 * 应用场景:<br>
 * CountDownLatch:异步转同步,,,<br>
 * CyclicBarrier:批量多线程汇总,像短时间跑批类的,<br>
 * 
 * 总结:<br>
 * CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。
 * 
 * @author Yuanqy
 *
 */
public class TestLatch {
    @org.junit.Test
    public void test() throws InterruptedException {
        // ==CountDownLatch===================================
        try {
            final CountDownLatch latch = new CountDownLatch(5);
            long i = latch.getCount();
            for (int j = 0; j < i; j++) {
                new Thread() {
                    @Override
                    public void run() {
                        System.out.println("CountDownLatch:" + latch.getCount() + "\t" + this.getName());//线程存在并发
                        latch.countDown();// 计数递减,当==0时 唤醒等待线程。
                    }
                }.start();// 异步执行
            }
            latch.await();// 阻塞,直到latch.getCount()==0时唤醒
            System.out.println("===Main1 is finish===");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // ==CyclicBarrier===================================
        final CyclicBarrier cb = new CyclicBarrier(5, new Thread() {
            @Override
            public void run() {
                System.out.println("===Last is finish===");//到达指定次数唤醒
            }
        });
        for (int i = 0; i < cb.getParties(); i++) {
            new Thread("Thread_" + i) {
                @Override
                public void run() {
                    try {
                        for (int x = 0; x < 2; x++) {// 我是可以重复使用的哦。
                            // cb.getNumberWaiting()返回已被await()的线程数量,不能用于计数。
                            Thread.sleep(500);
                            System.out.println("CyclicBarrier:" + cb.getNumberWaiting() + "\t" + this.getName());
                            cb.await();// 阻塞当前线程, 唤醒CyclicBarrier 预定的线程先执行,当前线程等待
                            System.out.println("Please watch me!\t" + this.getName());
                        }
                    } catch (InterruptedException | BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }.start();// 异步执行
        }
        System.out.println("===Main2 is finish===");//这里不阻塞
        Thread.currentThread().join();
    }
}
测试结果:
CountDownLatch:5    Thread-0
CountDownLatch:5    Thread-1
CountDownLatch:3    Thread-2
CountDownLatch:2    Thread-3
CountDownLatch:1    Thread-4
===Main1 is finish===
===Main2 is finish===
CyclicBarrier:0    Thread_2
CyclicBarrier:0    Thread_0
CyclicBarrier:0    Thread_1
CyclicBarrier:3    Thread_3
CyclicBarrier:4    Thread_4
===Last is finish===
Please watch me!    Thread_4
Please watch me!    Thread_0
Please watch me!    Thread_1
Please watch me!    Thread_2
Please watch me!    Thread_3
CyclicBarrier:0    Thread_0
CyclicBarrier:0    Thread_1
CyclicBarrier:0    Thread_4
CyclicBarrier:3    Thread_2
CyclicBarrier:4    Thread_3
===Last is finish===
Please watch me!    Thread_3
Please watch me!    Thread_2
Please watch me!    Thread_4
Please watch me!    Thread_1
Please watch me!    Thread_0
 
 
 
 
 

 