前言
目前正在出一个Java多线程专题
长期系列教程,从入门到进阶含源码解读
, 篇幅会较多, 喜欢的话,给个关注❤️ ~
Java提供了一些非常好用的并发工具类,不需要我们重复造轮子,本节我们讲解Phaser
,一起来看下吧~
Phaser
Phaser又称“阶段器”,用来解决多线程分阶段任务的场景。它与CountDownLatch和CyclicBarrier类似,都是等待一组线程完成工作后再执行下一步。但CountDownLatch和CyclicBarrier中不能动态的配置parties,而Phaser可以动态注册,相对而言更加的灵活。
常用方法
int register()
动态添加一个partiesint bulkRegister(int parties)
动态添加多个partiesint getRegisteredParties()
获取当前的parties数int arriveAndAwaitAdvance()
到达并等待其他线程到达int arriveAndDeregister()
到达并注销该parties,这个方法不会使线程阻塞int arrive()
到达,但不会使线程阻塞int awaitAdvance(int phase)
等待前行,可阻塞也可不阻塞,判断条件为phase,如果相等则阻塞int awaitAdvanceInterruptibly(int phase)
该方法与awaitAdvance类似,唯一不一样的就是它可以进行打断。int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit)
同上int getArrivedParties()
获取当前到达的parties数int getUnarrivedParties()
获取当前未到达的parties数int getPhase()
获取当前属于第几阶段,默认从0开始,最大为integer的最大值boolean isTerminated()
判断当前phaser是否关闭void forceTermination()
强制关闭当前phaser
示例
基本上把能用到的方法都给大家介绍了,下面我们通过一个例子实际体验一下:
public class PhaserTest { public static void main(String[] args) { Phaser phaser = new Phaser(10); for (int i=0; i<10; i++){ new Thread(() -> { try { long millis = System.currentTimeMillis(); System.out.println(millis + "--1-->当前处于"+phaser.getPhase()+"阶段"); Thread.sleep(1000); // wait phaser.arriveAndAwaitAdvance(); System.out.println(millis + "---2--->当前处于"+phaser.getPhase()+"阶段"); Thread.sleep(1000); // wait phaser.arriveAndAwaitAdvance(); System.out.println(millis + "---3--->当前处于"+phaser.getPhase()+"阶段"); Thread.sleep(1000); // wait phaser.arriveAndAwaitAdvance(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } System.out.println("主线程"); } } 复制代码
实际输出:
1659925927951--1-->当前处于0阶段 主线程 1659925927951--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927950--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927950--1-->当前处于0阶段 1659925927951--1-->当前处于0阶段 1659925927951---2--->当前处于1阶段 1659925927950---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927950---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---2--->当前处于1阶段 1659925927951---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927950---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927950---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 1659925927951---3--->当前处于2阶段 复制代码
可以看出并不会造成主线程的阻塞,任务也是分阶段去完成的, 其它方法就不一一演示了,大家可以自行操作一下
结束语
本节主要讲解它的一个使用,有兴趣的同学可以看一下它的底层源码实现,相对于前两个要复杂一点,这里就不过多介绍。下一节,给大家讲下Fork/Join
框架,关注我,不迷路 ~