CyclicBarrier与CountDownLatch区别
来源:互联网 发布:java中instanceof 编辑:程序博客网 时间:2024/05/17 04:39
阻塞与唤醒方式的区别
CountDownLatch计数方式
CountDownLatch是减计数。调用await()后线程阻塞。调用countDown()方法后计数减一,当计数为零时,调用await()的线程被唤醒。
CountDownLatch应用场景为:
一个或一组线程等待另一组线程完成操作后恢复执行
CountDownLatch例子: 模拟赛跑
开始时一组运动员线程等待begin计数器(初始值为1),当主线程调用begin.countDown()后begin减1,计数器为0,这一组运动员线程同时起跑。主线程等待end计数器(初始值为10)。一个运动员线程到达终点后,调用end.countDown(),end计数器减1。当所有运动员都到达终点后,end计数器为0,主线程恢复执行。
package CountDownLatch;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class RaceSimulation { public static void main(String args[]){ //比赛开始的倒数锁 CountDownLatch begin=new CountDownLatch(1); //比赛结束的倒数锁 CountDownLatch end=new CountDownLatch(10); //十个选手跑步线程 final ExecutorService exec = Executors.newFixedThreadPool(10); for(int index= 0;index<10;++index){ final int NO=index+1; Runnable run = new Runnable(){ @Override public void run() { try{ //如果计数不为0,则一直等待 //如果当前计数为0,此线程立即执行 begin.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("No."+NO+" arrived"); }catch(InterruptedException e){ e.printStackTrace(); }finally{ //每个选手到达终点时,end就减1 end.countDown(); } } }; exec.submit(run); } System.out.println("游戏开始:"); //begin减1,开始游戏 begin.countDown(); //等待end变为0,即所有选手到达终点 try { end.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("游戏结束"); exec.shutdown(); }}
CyclicBarrier计数方式
CyclicBarrier是加计数。调用await()后线程阻塞计数器加1,当所有线程都到达屏障被阻塞后,这一组线程才一起恢复执行。
CyclicBarrier的应用场景
一组线程到达一个屏障(即执行CyclicBarrier.await())时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
CyclicBarier的例子
package cyclicBarrier;import java.util.Random;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CyclicBarrierDemo { public static void main(String[] args) { int N=4; CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() { @Override public void run() { System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作"); } }); ExecutorService exec=Executors.newFixedThreadPool(4); for(int i=0;i<N;++i) { Runnable r=()->{ try { System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作"); //用睡眠代替线程的操作 Thread.sleep(new Random().nextInt(1000)); System.out.println("线程"+Thread.currentThread().getName()+"到达屏障"); cyclicBarrier.await(); System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }; exec.submit(r); } exec.shutdown(); }}
是否可以重用
CountDownLatch不可以重用
CyclicBarrier可以重用
package cyclicBarrier;import java.util.Random;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CyclicBarrierDemo { public static void main(String[] args) { int N=4; CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() { @Override public void run() { System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作"); } }); ExecutorService exec1=Executors.newFixedThreadPool(4); for(int i=0;i<N;++i) { Runnable r=()->{ try { System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作"); //用睡眠代替线程的操作 Thread.sleep(new Random().nextInt(1000)); System.out.println("线程"+Thread.currentThread().getName()+"到达屏障"); cyclicBarrier.await(); System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }; exec1.submit(r); } exec1.shutdown(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("CyclicBarrier重用"); ExecutorService exec2=Executors.newFixedThreadPool(4); for(int i=0;i<N;++i) { Runnable r=()->{ try { System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作"); //用睡眠代替线程的操作 Thread.sleep(new Random().nextInt(1000)); System.out.println("线程"+Thread.currentThread().getName()+"到达屏障"); cyclicBarrier.await(); System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }; exec2.submit(r); } exec2.shutdown(); }}
阅读全文
0 0
- CountDownLatch与CyclicBarrier区别
- CyclicBarrier与CountDownLatch区别
- CountDownLatch与CyclicBarrier的区别
- CountDownLatch与CyclicBarrier的区别
- CountDownLatch与CyclicBarrier的区别
- CountDownLatch与CyclicBarrier二者很重要的区别
- Java中CountDownLatch与CyclicBarrier的区别
- CyclicBarrier和CountDownLatch区别
- CyclicBarrier和CountDownLatch区别
- CyclicBarrier和CountDownLatch区别
- CyclicBarrier和CountDownLatch区别
- CountDownLatch 与 CyclicBarrier应用
- CountDownLatch与CyclicBarrier
- CountDownLatch与CyclicBarrier详解
- CountDownLatch与CyclicBarrier
- CountDownLatch与CyclicBarrier
- CountDownLatch与CyclicBarrier
- CountDownLatch与CyclicBarrier
- Be Unique
- MySql 常用命令
- LeetCode
- MySQL 添加注释(comment)
- Pointers on C——12 Using Structures and Pointers.2
- CyclicBarrier与CountDownLatch区别
- LeetCode题解 第一周
- Linux/Unix下grep命令使用的几个例子[grep Examples]
- Java集合框架主要成员
- 图片加载之Glide使用总结
- HDFS的安全模式
- Navicat无法连接Oracle 11g:Cannot load OCI DLL 87/193——解决办法
- 让Ubuntu 16.04可以压缩/解压缩RAR文件
- Qt Charts入门指南