Java并发编程 - Phaser类的使用( 二 )
< parties; i++) {executor.execute(new Runnable() {@Overridepublic void run() {try {//可以在任务执行开始时执行,表示所有的任务都启动后 , 主线程的await即可解除//latch.countDown();//run//..Thread.sleep(3000);} catch (Exception e) {}finally {//任务执行完毕后:到达//表示所有的任务都结束 , 主线程才能继续latch.countDown();}}});}latch.await();//主线程阻塞 , 直到所有的parties到达//latch上所有的parties都达到后 , 再次执行await将不会有效 ,//即barrier是不可重用的executor.shutdown();2、CyclicBarrier
Java代码
//创建时 , 就需要指定参与的parties个数int parties = 12;CyclicBarrier barrier = new CyclicBarrier(parties);//线程池中同步taskExecutorService executor = Executors.newFixedThreadPool(parties);for(int i = 0; i < parties; i++) {executor.execute(new Runnable() {@Overridepublic void run() {try {int i = 0;while (i < 3Thread.sleep(3000);//如果所有的parties都到达 , 则开启新的一次周期(generation)//barrier可以被重用barrier.await();i++;}} catch (Exception e) {e.printStackTrace();}finally {}}});}Thread.sleep(100000);
3、Phaser
Java代码
//创建时 , 就需要指定参与的parties个数int parties = 12;//可以在创建时不指定parties// 而是在运行时 , 随时注册和注销新的partiesPhaser phaser = new Phaser();//主线程先注册一个//对应下文中 , 主线程可以等待所有的parties到达后再解除阻塞(类似与CountDownLatch)phaser.register();ExecutorService executor = Executors.newFixedThreadPool(parties);for(int i = 0; i < parties; i++) {phaser.register();//每创建一个task , 我们就注册一个partyexecutor.execute(new Runnable() {@Overridepublic void run() {try {int i = 0;while (i < 3Thread.sleep(3000);//等待同一周期内 , 其他Task到达//然后进入新的周期 , 并继续同步进行phaser.arriveAndAwaitAdvance();i++;//我们假定 , 运行三个周期即可}} catch (Exception e) {}finally {phaser.arriveAndDeregister();}}});}//主线程到达 , 且注销自己//此后线程池中的线程即可开始按照周期 , 同步执行 。phaser.arriveAndDeregister();
三、API简述1、Phaser():构造函数 , 创建一个Phaser;默认parties个数为0 。 此后我们可以通过register()、bulkRegister()方法来注册新的parties 。 每个Phaser实例内部 , 都持有几个状态数据:termination状态、已经注册的parties个数(registeredParties)、当前phase下已到达的parties个数(arrivedParties)、当前phase周期数 , 还有2个同步阻塞队列Queue 。 Queue中保存了所有的waiter , 即因为advance而等待的线程信息;这两个Queue分别为evenQ和oddQ , 这两个Queue在实现上没有任何区别 , Queue的元素为QNode , 每个QNode保存一个waiter的信息 , 比如Thread引用、阻塞的phase、超时的deadline、是否支持interrupted响应等 。 两个Queue , 其中一个保存当前phase中正在使用的waiter , 另一个备用 , 当phase为奇数时使用evenQ、oddQ备用 , 偶数时相反 , 即两个Queue轮换使用 。 当advance事件触发期间 , 新register的parties将会被放在备用的Queue中 , advance只需要响应另一个Queue中的waiters即可 , 避免出现混乱 。
2、Phaser(int parties):构造函数 , 初始一定数量的parties;相当于直接regsiter此数量的parties 。
3、arrive():到达 , 阻塞 , 等到当前phase下其他parties到达 。 如果没有register(即已register数量为0) , 调用此方法将会抛出异常 , 此方法返回当前phase周期数 , 如果Phaser已经终止 , 则返回负数 。
4、arriveAndDeregister():到达 , 并注销一个parties数量 , 非阻塞方法 。 注销 , 将会导致Phaser内部的parties个数减一(只影响当前phase) , 即下一个phase需要等待arrive的parties数量将减一 。 异常机制和返回值 , 与arrive方法一致 。
5、arriveAndAwaitAdvance():到达 , 且阻塞直到其他parties都到达 , 且advance 。 此方法等同于awaitAdvance(arrive()) 。 如果你希望阻塞机制支持timeout、interrupted响应 , 可以使用类似的其他方法(参见下文) 。 如果你希望到达后且注销 , 而且阻塞等到当前phase下其他的parties到达 , 可以使用awaitAdvance(arriveAndDeregister())方法组合 。 此方法的异常机制和返回值同arrive() 。
6、awaitAdvance(int phase):阻塞方法 , 等待phase周期数下其他所有的parties都到达 。 如果指定的phase与Phaser当前的phase不一致 , 则立即返回 。
7、awaitAdvanceInterruptibly(int phase):阻塞方法 , 同awaitAdvance , 只是支持interrupted响应 , 即waiter线程如果被外部中断 , 则此方法立即返回 , 并抛出InterrutedException 。
8、awaitAdvanceInterruptibly(int phase,long timeout,TimeUnit unit):阻塞方法 , 同awaitAdvance , 支持timeout类型的interrupted响应 , 即当前线程阻塞等待约定的时长 , 超时后以TimeoutException异常方式返回 。
- 现状|程序员现状揭秘:平均年薪20.36万,Java人才需求量最大
- Store|苹果将在韩国开设第二家Apple Store直营店 并发布纪念壁
- Linux(服务器编程):百万并发服务器系统参数调优
- 程序员学英语第1天——JavaScript 程序测试的介绍1
- 三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经
- 《深入理解Java虚拟机》:对象创建、布局和访问全过程
- 菜鸟学编程,不懂C++ this指针?还不赶快来学一学
- java面试题整理
- Kotlin集合vs Kotlin序列与Java流
- 编程猫领衔,9家编程app测评一览详解