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