Java并发编程——CyclicBarrier和Phaser
来源:互联网 发布:mac谷歌浏览器无法登录 编辑:程序博客网 时间:2024/05/21 20:30
一、CyclicBarrier
CyclicBarrier拥有CountDownLatch的功能(CountDownLatch的介绍请看我的另一篇博客: Java并发编程——Semaphore (信号量)和CountDownLatch ),任何一个线程在没有完成时,所有线程都在等待。有点类似于屏障的意思,比如百米赛跑,需要等所有运动员都到达起跑线后,裁判才会鸣枪,这个“起跑线”就是屏障,每个运动员就是一个个线程,而“裁判鸣枪”就是后需要做的一些事情。
上栗子:
public static void main(String[] args) { final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() { @Override public void run() { //执行所有线程全部完成后的逻辑 try { System.out.println("执行所有线程全部完成后的逻辑 开始"); Thread.sleep(3000); System.out.println("执行所有线程全部完成后的逻辑 结束"); } catch (InterruptedException e) { e.printStackTrace(); } } }); //子线程数量 int threadNum = 4; for (int i = 0; i < threadNum; i++) { final int finalI = i; new Thread(new Runnable() { @Override public void run() { try { System.out.println("开始" + finalI); cyclicBarrier.await(); System.out.println("结束" + finalI); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }).start(); } }
简单粗暴,直接看log:
12-19 15:19:28.470 18459-18635/? I/System.out: 开始012-19 15:19:28.470 18459-18636/? I/System.out: 开始112-19 15:19:28.470 18459-18637/? I/System.out: 开始212-19 15:19:28.470 18459-18638/? I/System.out: 开始3
接下来改变线程数量:
//子线程数量 int threadNum = 5;
再次运行看log:
12-19 15:22:27.810 22580-22713/lbx.myapplication I/System.out: 开始012-19 15:22:27.810 22580-22715/lbx.myapplication I/System.out: 开始212-19 15:22:27.810 22580-22714/lbx.myapplication I/System.out: 开始112-19 15:22:27.810 22580-22716/lbx.myapplication I/System.out: 开始312-19 15:22:27.820 22580-22717/lbx.myapplication I/System.out: 开始412-19 15:22:27.820 22580-22717/lbx.myapplication I/System.out: 执行所有线程全部完成后的逻辑 开始//睡了三秒12-19 15:22:30.820 22580-22717/lbx.myapplication I/System.out: 执行所有线程全部完成后的逻辑 结束12-19 15:22:30.820 22580-22717/lbx.myapplication I/System.out: 结束412-19 15:22:30.820 22580-22713/lbx.myapplication I/System.out: 结束012-19 15:22:30.820 22580-22715/lbx.myapplication I/System.out: 结束212-19 15:22:30.820 22580-22714/lbx.myapplication I/System.out: 结束112-19 15:22:30.820 22580-22716/lbx.myapplication I/System.out: 结束3
常用方法:
//在此方法处线程阻塞,n个线程都执行await()后回调Runnable里的逻辑cyclicBarrier.await();//阻塞到3秒后则抛出TimeoutException异常,不会继续向下执行cyclicBarrier.await(3, TimeUnit.SECONDS);//获得到达await()(屏障)的线程的数量cyclicBarrier.getNumberWaiting();//当前线程的屏障是否出现损坏,例如终止线程的时候cyclicBarrier.isBroken();//获取屏障的数量:ncyclicBarrier.getParties();//重置屏障cyclicBarrier.reset();
二、Phaser
与CyclicBarrier功能重叠,任何一个线程在没有完成时,所有线程都在等待。
public static void main(String[] args) { final Phaser phaser = new Phaser(5) { @Override protected boolean onAdvance(int phase, int registeredParties) { //当所有线程都完成了一个任务的时候,会回调。 System.out.println("完成了第" + phase + "个屏障"); //true:后面的屏障无效。false:保持屏障的有效性 return false; } }; //线程数量 int threadNum = 5; for (int i = 0; i < threadNum; i++) { final int finalI = i; new Thread(new Runnable() { @Override public void run() { try { System.out.println("开始" + finalI); Thread.sleep(1000); //与CyclicBarrier相同,都是等待所有线程到达屏障后,再统一释放 phaser.arriveAndAwaitAdvance(); System.out.println("结束" + finalI); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }
重写了onAdvance方法,该方法在所有线程执行arriveAndAwaitAdvance后调用。看下log:
12-19 16:28:13.310 16518-16709/lbx.myapplication I/System.out: 开始012-19 16:28:13.310 16518-16710/lbx.myapplication I/System.out: 开始112-19 16:28:13.310 16518-16711/lbx.myapplication I/System.out: 开始212-19 16:28:13.320 16518-16712/lbx.myapplication I/System.out: 开始312-19 16:28:13.320 16518-16713/lbx.myapplication I/System.out: 开始412-19 16:28:14.320 16518-16713/lbx.myapplication I/System.out: 完成了第0个屏障12-19 16:28:14.320 16518-16709/lbx.myapplication I/System.out: 结束012-19 16:28:14.320 16518-16713/lbx.myapplication I/System.out: 结束412-19 16:28:14.320 16518-16710/lbx.myapplication I/System.out: 结束112-19 16:28:14.320 16518-16711/lbx.myapplication I/System.out: 结束212-19 16:28:14.320 16518-16712/lbx.myapplication I/System.out: 结束3
接下来我们把线程的数量翻倍:
//线程数量 int threadNum = 10;
再次运行,看log:
12-19 16:32:56.440 23790-25143/lbx.myapplication I/System.out: 开始012-19 16:32:56.440 23790-25144/lbx.myapplication I/System.out: 开始112-19 16:32:56.440 23790-25145/lbx.myapplication I/System.out: 开始212-19 16:32:56.440 23790-25146/lbx.myapplication I/System.out: 开始312-19 16:32:56.440 23790-25147/lbx.myapplication I/System.out: 开始412-19 16:32:56.440 23790-25148/lbx.myapplication I/System.out: 开始512-19 16:32:56.440 23790-25149/lbx.myapplication I/System.out: 开始612-19 16:32:56.440 23790-25150/lbx.myapplication I/System.out: 开始712-19 16:32:56.440 23790-25151/lbx.myapplication I/System.out: 开始812-19 16:32:56.440 23790-25152/lbx.myapplication I/System.out: 开始912-19 16:32:57.440 23790-25146/lbx.myapplication I/System.out: 完成了第0个屏障12-19 16:32:57.440 23790-25145/lbx.myapplication I/System.out: 结束212-19 16:32:57.440 23790-25146/lbx.myapplication I/System.out: 结束312-19 16:32:57.440 23790-25147/lbx.myapplication I/System.out: 结束412-19 16:32:57.440 23790-25144/lbx.myapplication I/System.out: 结束112-19 16:32:57.440 23790-25143/lbx.myapplication I/System.out: 结束012-19 16:32:57.440 23790-25152/lbx.myapplication I/System.out: 完成了第1个屏障12-19 16:32:57.440 23790-25152/lbx.myapplication I/System.out: 结束912-19 16:32:57.440 23790-25149/lbx.myapplication I/System.out: 结束612-19 16:32:57.440 23790-25150/lbx.myapplication I/System.out: 结束712-19 16:32:57.440 23790-25148/lbx.myapplication I/System.out: 结束512-19 16:32:57.440 23790-25151/lbx.myapplication I/System.out: 结束8
因为onAdvance返回的是false,第一次执行过onAdvance后,屏障依然有效,所以后面的代码正常执行,当我们把onAdvance返回true的时候,仍然用10条子线程:
final Phaser phaser = new Phaser(5) { @Override protected boolean onAdvance(int phase, int registeredParties) { //当所有线程都完成了一个任务的时候,会回调。 System.out.println("完成了第" + phase + "个屏障"); //true:后面的屏障无效。false:保持屏障的有效性 return true; } };
运行代码,看log:
12-19 16:35:19.050 27494-28566/lbx.myapplication I/System.out: 开始012-19 16:35:19.050 27494-28568/lbx.myapplication I/System.out: 开始212-19 16:35:19.050 27494-28567/lbx.myapplication I/System.out: 开始112-19 16:35:19.050 27494-28569/lbx.myapplication I/System.out: 开始312-19 16:35:19.050 27494-28570/lbx.myapplication I/System.out: 开始412-19 16:35:19.050 27494-28571/lbx.myapplication I/System.out: 开始512-19 16:35:19.050 27494-28572/lbx.myapplication I/System.out: 开始612-19 16:35:19.050 27494-28573/lbx.myapplication I/System.out: 开始712-19 16:35:19.050 27494-28574/lbx.myapplication I/System.out: 开始812-19 16:35:19.050 27494-28575/lbx.myapplication I/System.out: 开始912-19 16:35:20.050 27494-28570/lbx.myapplication I/System.out: 完成了第0个屏障12-19 16:35:20.050 27494-28570/lbx.myapplication I/System.out: 结束412-19 16:35:20.050 27494-28568/lbx.myapplication I/System.out: 结束212-19 16:35:20.050 27494-28571/lbx.myapplication I/System.out: 结束512-19 16:35:20.050 27494-28566/lbx.myapplication I/System.out: 结束012-19 16:35:20.050 27494-28567/lbx.myapplication I/System.out: 结束112-19 16:35:20.050 27494-28572/lbx.myapplication I/System.out: 结束612-19 16:35:20.050 27494-28569/lbx.myapplication I/System.out: 结束312-19 16:35:20.050 27494-28573/lbx.myapplication I/System.out: 结束712-19 16:35:20.050 27494-28574/lbx.myapplication I/System.out: 结束812-19 16:35:20.050 27494-28575/lbx.myapplication I/System.out: 结束9
我们发现,onAdvance只执行了一次,因为反悔了true,使屏障无效了,那么也就没有屏障的概念了。
常用方法:
//获得当前parties的个数phaser.getRegisteredParties();//使parties的个数加1phaser.register();//使parties的个数加3phaser.bulkRegister(3);//获得当前已经被使用的parties的个数phaser.getArrivedParties();//获得当前未被使用的parties的个数phaser.getUnarrivedParties();//使parties的个数加1,并继续往下执行,回调onAdvance()方法phaser.arrive();//若传入的参数与getPhase()的值一样,则处于屏障阻塞状态,否则继续往下执行过。该方法不参与计算,只起判断作用phaser.awaitAdvance(3);
阅读全文
0 0
- Java并发编程——CyclicBarrier和Phaser
- Java并发-同步器CyclicBarrier,Exchanger,Phaser
- Java并发之CyclicBarrier、CountDownLatch、Phaser
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 《Java 7 并发编程指南》学习概要 (3)Semaphore, CountDownLatch, CyclicBarrier , Phaser, Exchanger
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Lua垃圾回收及内存优化
- c
- 将tomcat源码打包为源代码包
- 12.14笔记
- json标准中,字符串是用双引号
- Java并发编程——CyclicBarrier和Phaser
- 闪迪SanDisk优盘USB3.0故障USB2.0正常的权宜处理
- ie8在使用stringify后中文变unicode问题解决
- 【lintcode】最大子数组
- vim的基本设置环境
- 72. Edit Distance
- 从零开始搭建MVC项目
- linux上iostat命令
- 单链表的反转