Phaser 类简介
Phaser 类是一种同步机制,用于控制以并发方式划分为多个阶段的算法的执行。
如果处理过程已有明确定义的步骤,那么必须在开始第二个步骤之前完成第一步的工作,以此类推,并且可以使用 Phaser 类实现该过程的并发版本。
Phaser 类的主要特征有以下几点。
-
分段器(phaser)必须知道要控制的任务数。
Java 称之为参与者的注册机制。参与者可以随时在分段器中注册。 - 任务完成一个阶段之后必须通知分段器。
在所有参与者都完成该阶段之前,分段器将使该任务处于休眠状态。 - 在内部,分段器保存了一个整数值,该值存储分段器已经进行的阶段变更数目。
- 参与者可以随时脱离分段器的控制。
Java 将这一过程称为参与者的注销。 - 当分段器做出阶段变更时,可以执行定制的代码。
- 控制分段器的终止。
如果一个分段器终止了,就不再接受新的参与者,也不会进行任务之间的同步。 - 通过一些方法获得分段器的参与者数目及其状态。
参与者的注册与注销
一个分段器必须知道其控制的任务数目,必须知道正在执行划分为多个阶段的算法的不同线程数目,以便正确控制同时发生的阶段变更。
Java 将此过程称作参与者的注册。
正常情况下,参与者在执行开始时注册,但是也可以随时注册。
可以采用不同方式注册参与者,如下所示。
- 创建 Phaser 对象时:Phaser 类提供了四个不同的构造函数。
其中常用的有两个。Phaser()
:该构造函数创建了一个 0 个参与者的分段器。Phaser(int parties)
:该构造函数创建了一个含有给定数目参与者的分段器。
- 还可以通过下述方法显式创建。
bulkRegisterl(int parties)
:同时注册给定数目的新参与者 。register()
:注册一个新参与者。
分段器控制的任务完成执行时,必须从分段器注销。
如果不这样做,分段器就会在下一阶段变更中一直等待该任务。
注销一个参与者,可以使用 arriveAndDeregister()
方法。
使用该方法告知分段器该任务已经完成了当前阶段,而且不再参与下一阶段。
同步阶段变更
分段器的主要目的是使那些可以分割成多个阶段的算法以并发方式执行。
所有任务完成当前阶段之前,任何任务都不能进入下一阶段。
Phaser 类提供了 arrive()
、 arriveAndDeregister()
和 arriveAndAwaitAdvance()
三个方法通报任务已经完成当前阶段。
如果其中某个任务没有调用上述三个方法之一,那么分段器对其他参与任务的阻塞是不确定的。
继续进入下一阶段需要用到下述方法。
-
arriveAndAwaitAdvance()
:
任务使用该方法向分段器通报,表明它已经完成了当前阶段并且要继续下一阶段。
分段器将阻塞该任务,直到所有参与的任务已调用其中一个同步方法。 -
awaitAdvance(int phase)
:
任务使用该方法向分段器通报,如果该方法参数中的数值和分段器的实际阶段数相等,就要等待当前阶段结束;如果这两个数值不相等,则该方法立即返回。
其他功能
在所有参与任务都完成了某个阶段的执行之后,在继续下一阶段之前, Phaser 类执行 onAdvance()
方法。
该方法接收如下两个参数。
phase
:
这是已执行完毕阶段的编号。第一个阶段的编号为 0。registeredParties
:
这个参数代表参与任务的数目。
如果想在两个阶段之间执行一些代码,例如,对某些数据进行排序或者转换,那么可以扩展 Phaser 类并重载该方法以实现自己的分段器。
分段器可以有以下两种状态。
-
激活状态:
创建了分段器且新的参与者注册后,分段器将进入激活状态,并持续这种状态,直到其终止。
处于这种状态时,它接受新的参与者并像之前所述那样工作。 -
终止状态:
onAdvance() 方法返回 true 值时,分段器进入这种状态。
默认情况下,当所有参与者都注销后, onAdvance() 方法将返回 true 值。
获取分段器状态和其中参与者的信息
Phaser 类提供了一些方法,获取分段器状态和其中参与者的信息。
getRegisteredParties()
:该方法返回分段器中参与者的数目。getPhase()
:该方法返回当前阶段的编号。getArrivedParties()
:该方法返回已经完成当前阶段的参与者的数目。getUnarrivedParties()
:该方法返回尚未完成当前阶段的参与者的数目。isTerminated()
:如果分段器处于终止状态,则该方法返回 true 值,否则返回 false值。