CountDownLatch、CyclicBarrier 的对比

原创
2016/11/11 17:36
阅读数 477

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

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部