CyclicBarrier和CountDownLatch的区别

来源:互联网 发布:2016淘宝运营教程下载 编辑:程序博客网 时间:2024/05/29 09:15

CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。
CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。
CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
而CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.

CountDownLatchCyclicBarrier减计数方式加计数方式计算为0时释放所有等待的线程计数达到指定值时释放所有等待线程计数为0时,无法重置计数达到指定值时,计数置为0重新开始调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞不可重复利用可重复利用下面这3个方法是CountDownLatch类中最重要的方法:

public void await() throws InterruptedException { };   //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行  public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行  public void countDown() { };  //将count值减1 
一个关于CountDownLatch的简单demo:

package Thread;import java.util.concurrent.CountDownLatch;public class CountDownLatchTest {public static void main(String[] args) {//5为计数值CountDownLatch countDownLatch = new CountDownLatch(5);for (int i = 1; i < 6; i++) {new Thread(new readNum(i, countDownLatch)).start();}try {//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行//此时是主线程被挂起,等5个子线程执行完成后主线程接着执行countDownLatch.await();//让主线程睡1000ms让结果更明显Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("主线程执行结束。。。。");}static class readNum implements Runnable {private int id;private CountDownLatch latch;public readNum(int id, CountDownLatch latch) {this.id = id;this.latch = latch;}@Overridepublic void run() {synchronized (this) {System.out.println("id:" + id);//调用countDown()方法,将countDownLatch值减1latch.countDown();System.out.println("线程组任务" + id + "结束,其他任务继续");try {//线程睡100ms,让结果更明显Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}}  }
执行结果如下:

id:2线程组任务2结束,其他任务继续id:3线程组任务3结束,其他任务继续id:5id:4线程组任务4结束,其他任务继续id:1线程组任务5结束,其他任务继续线程组任务1结束,其他任务继续线程执行结束。。。。
可以看出来,只有主线程调用了await()方法并且阻塞,即就是只有主线程等待其他的5个子线程执行完成,主线程在接着向下执行

一个关于CyclicBarrier的简单demo:

package Thread;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;public class CyclicBarrierTest2 {public static void main(String[] args) {//定义6个线程需要等待CyclicBarrier cyclicBarrier = new CyclicBarrier(6);for (int i = 0; i < 5; i++) {new Thread(new readNum(i, cyclicBarrier)).start();}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {//主线程睡1000ms,等子线程全部执行完成后,主线程在调用await()方法,//将count值加1,此时cyclicBarrier的count值已经等于6,全部的线程开始接着向下执行cyclicBarrier.await();} catch (InterruptedException | BrokenBarrierException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}//主线程在睡1000ms,等5个子线程都打印完成,在接着向下执行try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("主线程执行结束。。。。");}static class readNum implements Runnable {private int id;private CyclicBarrier barrier;public readNum(int id, CyclicBarrier barrier) {this.id = id;this.barrier = barrier;}@Overridepublic void run() { {System.out.println("id:" + id);try {//每一个线程进来调用await()方法,将barrier的count值加1barrier.await();System.out.println("线程组任务" + id + "结束,其他任务继续");} catch (BrokenBarrierException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}  }
运行结果如下所示:

id:1
id:2
id:0
id:3
id:4
线程组任务1结束,其他任务继续
线程组任务0结束,其他任务继续
线程组任务4结束,其他任务继续
线程组任务2结束,其他任务继续
线程组任务3结束,其他任务继续
主线程执行结束。。。。
可以看出来,主线程和每个子线程都调用了await()方法,他们之间是相互等待的。



原创粉丝点击