CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.
区别:
1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。
2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。
3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier 唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。
应用场景:
CountDownLatch:异步转同步,,,
CyclicBarrier:批量多线程汇总,像短时间跑批类的,
总结:
CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。
1package test; 2 3import java.util.concurrent.BrokenBarrierException; 4import java.util.concurrent.CountDownLatch; 5import java.util.concurrent.CyclicBarrier; 6 7/** 8 * CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.<br> 9 * 10 * 区别:<br> 11 * 1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。<br> 12 * 2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。<br> 13 * 3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。<br> 14 * 15 * 应用场景:<br> 16 * CountDownLatch:异步转同步,,,<br> 17 * CyclicBarrier:批量多线程汇总,像短时间跑批类的,<br> 18 * 19 * 总结:<br> 20 * CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。 21 * 22 * @author Yuanqy 23 * 24 */ 25public class TestLatch { 26 27 @org.junit.Test 28 public void test() throws InterruptedException { 29 // ==CountDownLatch=================================== 30 try { 31 final CountDownLatch latch = new CountDownLatch(5); 32 long i = latch.getCount(); 33 for (int j = 0; j < i; j++) { 34 new Thread() { 35 @Override 36 public void run() { 37 System.out.println("CountDownLatch:" + latch.getCount() + "\t" + this.getName());//线程存在并发 38 latch.countDown();// 计数递减,当==0时 唤醒等待线程。 39 } 40 }.start();// 异步执行 41 } 42 latch.await();// 阻塞,直到latch.getCount()==0时唤醒 43 System.out.println("===Main1 is finish==="); 44 } catch (InterruptedException e) { 45 e.printStackTrace(); 46 } 47 // ==CyclicBarrier=================================== 48 final CyclicBarrier cb = new CyclicBarrier(5, new Thread() { 49 @Override 50 public void run() { 51 System.out.println("===Last is finish===");//到达指定次数唤醒 52 } 53 }); 54 for (int i = 0; i < cb.getParties(); i++) { 55 new Thread("Thread_" + i) { 56 @Override 57 public void run() { 58 try { 59 for (int x = 0; x < 2; x++) {// 我是可以重复使用的哦。 60 // cb.getNumberWaiting()返回已被await()的线程数量,不能用于计数。 61 Thread.sleep(500); 62 System.out.println("CyclicBarrier:" + cb.getNumberWaiting() + "\t" + this.getName()); 63 cb.await();// 阻塞当前线程, 唤醒CyclicBarrier 预定的线程先执行,当前线程等待 64 System.out.println("Please watch me!\t" + this.getName()); 65 } 66 } catch (InterruptedException | BrokenBarrierException e) { 67 e.printStackTrace(); 68 } 69 } 70 }.start();// 异步执行 71 } 72 System.out.println("===Main2 is finish===");//这里不阻塞 73 Thread.currentThread().join(); 74 } 75}
测试结果:
1CountDownLatch:5 Thread-0 2CountDownLatch:5 Thread-1 3CountDownLatch:3 Thread-2 4CountDownLatch:2 Thread-3 5CountDownLatch:1 Thread-4 6===Main1 is finish=== 7===Main2 is finish=== 8CyclicBarrier:0 Thread_2 9CyclicBarrier:0 Thread_0 10CyclicBarrier:0 Thread_1 11CyclicBarrier:3 Thread_3 12CyclicBarrier:4 Thread_4 13===Last is finish=== 14Please watch me! Thread_4 15Please watch me! Thread_0 16Please watch me! Thread_1 17Please watch me! Thread_2 18Please watch me! Thread_3 19CyclicBarrier:0 Thread_0 20CyclicBarrier:0 Thread_1 21CyclicBarrier:0 Thread_4 22CyclicBarrier:3 Thread_2 23CyclicBarrier:4 Thread_3 24===Last is finish=== 25Please watch me! Thread_3 26Please watch me! Thread_2 27Please watch me! Thread_4 28Please watch me! Thread_1 29Please watch me! Thread_0