CycliBarriar和CountdownLatch有什么区别?
4 个回答
你爱你的玫瑰是因为你在你的玫瑰上花了太多的时间!小王子-B513### CyclicBarrier和CountDownLatch的区别 #### 相似点 - 都位于 `java.util.concurrent` 包中。 - 都可以用来协调多个线程在某个点上进行同步操作。 #### 区别 1. **同步机制** - **CyclicBarrier**:当某个线程运行到指定点时,该线程停止运行,直到所有线程都到达这个点。所有线程在屏障点等待,直到最后一个线程到达屏障点,所有线程才重新运行。 - **CountDownLatch**:某线程运行到指定点后,只是将计数器减1,然后继续运行。其他线程可以在计数器减到0时继续执行,不需要所有线程都在同一个点等待。 2. **唤起任务** - **CyclicBarrier**:只能唤起一个任务(所有线程都到达屏障点后触发)。 - **CountDownLatch**:可以唤起多个任务。计数器减到0时,可以唤起等待在 `await` 方法上的所有线程。 3. **重用性** - **CyclicBarrier**:可重用。当所有线程到达屏障点并被唤醒后,CyclicBarrier 可以再次使用。 - **CountDownLatch**:不可重用。计数器减到0后,CountDownLatch 就不能再使用。 ### 示例代码 #### CyclicBarrier 示例 ```java import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierExample { public static void main(String[] args) { int numThreads = 3; CyclicBarrier barrier = new CyclicBarrier(numThreads, () -> { System.out.println("All threads have reached the barrier, proceeding..."); }); for (int i = 0; i < numThreads; i++) { new Thread(new Task(barrier)).start(); } } } class Task implements Runnable { private CyclicBarrier barrier; public Task(CyclicBarrier barrier) { this.barrier = barrier; } @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " is waiting at the barrier"); barrier.await(); System.out.println(Thread.currentThread().getName() + " has crossed the barrier"); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } } } ``` #### CountDownLatch 示例 ```java import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int numThreads = 3; CountDownLatch latch = new CountDownLatch(numThreads); for (int i = 0; i < numThreads; i++) { new Thread(new Worker(latch)).start(); } latch.await(); // 主线程等待所有工作线程完成 System.out.println("All threads have finished, proceeding with main thread..."); } } class Worker implements Runnable { private CountDownLatch latch; public Worker(CountDownLatch latch) { this.latch = latch; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " is doing some work"); latch.countDown(); System.out.println(Thread.currentThread().getName() + " has finished work"); } } ``` ### 总结 - **CyclicBarrier**: - 用于让一组线程在某个点上互相等待,直到所有线程都到达这个点。 - 只能唤起一个任务。 - 可重用。 - **CountDownLatch**: - 用于让一组线程在某个点上计数,计数器到达零时唤起所有等待的线程。 - 可以唤起多个任务。 - 不可重用。 这些工具类在并发编程中各有用途,根据具体场景选择合适的同步机制可以有效地管理线程之间的协调与通信。发布于 2024-07-06 06:55 •IP属地 北京举报评论收藏
快乐出现的时候,就好好享受快乐。宁大CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行; 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行; 另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。 CountdownLatch测试类: ```java import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * 测试多个线程结束后开始线程 */ public class TestCountDownLatch { public static void main(String[] args) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(5); Executor executor = Executors.newFixedThreadPool(5); //测试阻塞其他线程 new Thread(new MyRunnable(countDownLatch)).start(); //为了测试效果进行线程休眠 Thread.sleep(1000); for(int i = 1;i<=5;i++){ countDownLatch.countDown(); System.out.println("第"+i+"调用countDown方法结束"); //为了测试效果进行线程休眠 Thread.sleep(1000); } /* * 测试阻塞主线程 for (int i = 1; i <= 5; i++) { new Thread(new MyRunnable1(countDownLatch,i+"")).start(); Thread.sleep(1000); } try { System.out.println("主线程阻塞"); countDownLatch.await(); System.out.println("主线程继续执行"); } catch (InterruptedException e) { e.printStackTrace(); } */ } } class MyRunnable implements Runnable { CountDownLatch countDownLatch; public MyRunnable(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { System.out.println("进入线程,即将进入阻塞状态"); //调用await进行线程阻塞 countDownLatch.await(); System.out.println("线程进行执行..."); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyRunnable1 implements Runnable { private CountDownLatch countDownLatch; private String mark; public MyRunnable1(CountDownLatch countDownLatch, String mark) { super(); this.countDownLatch = countDownLatch; this.mark = mark; } @Override public void run() { System.out.println(mark+"号线程开始"); try { //使线程休眠,看到更好的测试效果 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(mark+"号线程结束"); //调用CountDownLatch的countDown方法进行次数减1 countDownLatch.countDown(); } public CountDownLatch getCountDownLatch() { return countDownLatch; } public void setCountDownLatch(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public String getMark() { return mark; } public void setMark(String mark) { this.mark = mark; } } ``` CyclicBarrier 测试类: ```java import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * 测试CyclicBarrier类的使用 */ public class TestCyclicBarrier { static final Integer NUM = 5; public static void main(String[] args) throws InterruptedException { //实例CyclicBarrier对象 CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM); //实例化一个固定大小线程池 Executor executor = Executors.newFixedThreadPool(NUM); for(int i = 1;i<=NUM;i++){ //执行线程 executor.execute(new MyRunnale(cyclicBarrier,i+"号")); //为了更好的效果,休眠一秒 Thread.sleep(1000); } System.out.println("指令通知完成"); } } class MyRunnale implements Runnable{ private CyclicBarrier cyclicBarrier; private String mark; public MyRunnale(CyclicBarrier cyclicBarrier,String mark) { super(); this.cyclicBarrier = cyclicBarrier; this.mark = mark; } @Override public void run() { System.out.println(mark+"进入线程,线程阻塞中..."); try { // barrier的await方法,在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。 cyclicBarrier.await(); Thread.sleep(2000);//为了看到更好的效果,线程阻塞两秒 } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(mark+"线程阻塞结束,继续执行..."); } public CyclicBarrier getCyclicBarrier() { return cyclicBarrier; } public void setCyclicBarrier(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } } ```编辑于 2022-11-26 21:23 •IP属地 天津举报评论收藏
醉后不知天在水,满船清梦压星河。李后才CyclicBarrier可以重复使用,而CountdownLatch不能重复使用。 Java的concurrent包里面的CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值。可以向CountDownLatch对象设置一个初始的数字作为计数值,任何调用这个对象上的await()方法都会阻塞,直到这个计数器的计数值被其他的线程减为0为止。所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。 CountDownLatch一个非常典型的应用场景:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。 CyclicBarrier一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。编辑于 2022-03-27 20:06 •IP属地 浙江举报评论收藏
明知不可为而为之就是我最大的诚意夜太CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行; 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行; 另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。 CountdownLatch测试类: ```java import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * 测试多个线程结束后开始线程 */ public class TestCountDownLatch { public static void main(String[] args) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(5); Executor executor = Executors.newFixedThreadPool(5); //测试阻塞其他线程 new Thread(new MyRunnable(countDownLatch)).start(); //为了测试效果进行线程休眠 Thread.sleep(1000); for(int i = 1;i<=5;i++){ countDownLatch.countDown(); System.out.println("第"+i+"调用countDown方法结束"); //为了测试效果进行线程休眠 Thread.sleep(1000); } /* * 测试阻塞主线程 for (int i = 1; i <= 5; i++) { new Thread(new MyRunnable1(countDownLatch,i+"")).start(); Thread.sleep(1000); } try { System.out.println("主线程阻塞"); countDownLatch.await(); System.out.println("主线程继续执行"); } catch (InterruptedException e) { e.printStackTrace(); } */ } } class MyRunnable implements Runnable { CountDownLatch countDownLatch; public MyRunnable(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { System.out.println("进入线程,即将进入阻塞状态"); //调用await进行线程阻塞 countDownLatch.await(); System.out.println("线程进行执行..."); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyRunnable1 implements Runnable { private CountDownLatch countDownLatch; private String mark; public MyRunnable1(CountDownLatch countDownLatch, String mark) { super(); this.countDownLatch = countDownLatch; this.mark = mark; } @Override public void run() { System.out.println(mark+"号线程开始"); try { //使线程休眠,看到更好的测试效果 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(mark+"号线程结束"); //调用CountDownLatch的countDown方法进行次数减1 countDownLatch.countDown(); } public CountDownLatch getCountDownLatch() { return countDownLatch; } public void setCountDownLatch(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public String getMark() { return mark; } public void setMark(String mark) { this.mark = mark; } } ``` CyclicBarrier 测试类: ```java import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * 测试CyclicBarrier类的使用 */ public class TestCyclicBarrier { static final Integer NUM = 5; public static void main(String[] args) throws InterruptedException { //实例CyclicBarrier对象 CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM); //实例化一个固定大小线程池 Executor executor = Executors.newFixedThreadPool(NUM); for(int i = 1;i<=NUM;i++){ //执行线程 executor.execute(new MyRunnale(cyclicBarrier,i+"号")); //为了更好的效果,休眠一秒 Thread.sleep(1000); } System.out.println("指令通知完成"); } } class MyRunnale implements Runnable{ private CyclicBarrier cyclicBarrier; private String mark; public MyRunnale(CyclicBarrier cyclicBarrier,String mark) { super(); this.cyclicBarrier = cyclicBarrier; this.mark = mark; } @Override public void run() { System.out.println(mark+"进入线程,线程阻塞中..."); try { // barrier的await方法,在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。 cyclicBarrier.await(); Thread.sleep(2000);//为了看到更好的效果,线程阻塞两秒 } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(mark+"线程阻塞结束,继续执行..."); } public CyclicBarrier getCyclicBarrier() { return cyclicBarrier; } public void setCyclicBarrier(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } } ```发布于 2022-03-16 23:33 •IP属地 西藏举报评论收藏
公众号进入网站体验更佳

