并发编程原理与实战(四)经典并发协同方式synchronized与wait+notify详解
并发编程原理与实战(五)经典并发协同方式伪唤醒与加锁失效原理揭秘
并发编程原理与实战(六)详解并发协同利器CountDownLatch
并发编程原理与实战(七)详解并发协同利器CyclicBarrier
上一篇讲解了线程在Phaser相位器上注册与注销的概念、阶段号的概念、相位器分层的背景与作用以及相位器监控的概念,本文继续对Phaser相位器相关api方法进一步学习。
Phaser核心方法
Phaser的核心方法主要包括创建Phaser对象的构造函数,参与者线程注册与注销相关方法、线程同步控制相关方法、阶段终止相关方法、相位器状态查询相关方法,下面我们来逐类分析讲解下。
构造函数
1、Phaser()
/**
* Creates a new phaser with no initially registered parties, no
* parent, and initial phase number 0. Any thread using this
* phaser will need to first register for it.
*/
public Phaser() {
this(null, 0);
}
创建一个没有初始参与线程数的相位器,没有父相位器且初始阶段号为0,任何使用该相位器的线程都必须先注册。
2、Phaser(int parties)
/**
* Creates a new phaser with the given number of registered
* unarrived parties, no parent, and initial phase number 0.
*
* @param parties the number of parties required to advance to the
* next phase
* @throws IllegalArgumentException if parties less than zero
* or greater than the maximum number of parties supported
*/
public Phaser(int parties) {
this(null, parties);
}
根据给定的注册未到达的参者数量创建一个相位器,没有父相位器且初始阶段号为0。参数parties指定需要进入到下一个阶段的参与者数量,如果参与者数量小于0或者大于最大值将会抛出非法数据异常。
3、Phaser(Phaser parent)
/**
* Equivalent to {@link #Phaser(Phaser, int) Phaser(parent, 0)}.
*
* @param parent the parent phaser
*/
public Phaser(Phaser parent) {
this(parent, 0);
}
指定父相位器创建子相位器,子相位器作为整体注册到父相位器中。
4、Phaser(Phaser parent, int parties)
/**
* Creates a new phaser with the given parent and number of
* registered unarrived parties. When the given parent is non-null
* and the given number of parties is greater than zero, this
* child phaser is registered with its parent.
*
* @param parent the parent phaser
* @param parties the number of parties required to advance to the
* next phase
* @throws IllegalArgumentException if parties less than zero
* or greater than the maximum number of parties supported
*/
public Phaser(Phaser parent, int parties) {
if (parties >>> PARTIES_SHIFT != 0)
throw new IllegalArgumentException("Illegal number of parties");
int phase = 0;
this.parent = parent;
if (parent != null) {
final Phaser root = parent.root;
this.root = root;
this.evenQ = root.evenQ;
this.oddQ = root.oddQ;
if (parties != 0)
phase = parent.doRegister(1);
}
else {
this.root = this;
this.evenQ = new AtomicReference<QNode>();
this.oddQ = new AtomicReference<QNode>();
}
this.state = (parties == 0) ? (long)EMPTY :
((long)phase << PHASE_SHIFT) |
((long)parties << PARTIES_SHIFT) |
((long)parties);
}
指定父相位器和未到达的参与者数量创建子相位器,当父相位器不为空且给定的参与者数量大于0时,子相位器将会注册到父相位器中。
线程注册与注销
1、int register()
/**
* Adds a new unarrived party to this phaser. If an ongoing
* invocation of {@link #onAdvance} is in progress, this method
* may await its completion before returning. If this phaser has
* a parent, and this phaser previously had no registered parties,
* this child phaser is also registered with its parent. If
* this phaser is terminated, the attempt to register has
* no effect, and a negative value is returned.
*
* @return the arrival phase number to which this registration
* applied. If this value is negative, then this phaser has
* terminated, in which case registration has no effect.
* @throws IllegalStateException if attempting to register more
* than the maximum supported number of parties
*/
public int register() {
return doRegister(1);
}
调用该方法增加一个新的未到达的参与者(任务)到相位器中。如果正在调用onAdvance()方法,该方法在返回前会等待onAdvance()方法完成。如果该相位器有一个父相位器,并且该相位器之前没有注册参与者,这个子相位器同样会注册到父相位器中。如果该相位器已经终止了,那么注册会没有任何效果,并返回一个负值。
该方法会返回当前的阶段号(phase number),如果返回的是负值,表明这个相位器已经终止了,在这种情况下,注册是无效的。如果尝试注册大于最大值数量的线程,将会抛出非法状态异常。
2、int bulkRegister(int parties)
/**
...
*
* @param parties the number of additional parties required to
* advance to the next phase
* @return the arrival phase number to which this registration
* applied. If this value is negative, then this phaser has
* terminated, in which case registration has no effect.
* @throws IllegalStateException if attempting to register more
* than the maximum supported number of parties
* @throws IllegalArgumentException if {@code parties < 0}
*/
public int bulkRegister(int parties) {
if (parties < 0)
throw new IllegalArgumentException();
if (parties == 0)
return getPhase();
return doRegister(parties);
}
调用该方法增加指定数量未到达的参与者(任务)到相位器中,bulk是大批量的意思,相当于批量注册多个参与者。如果传入的参与者数量小于0,则抛出非法数据异常。其他同register()方法。
3、int arriveAndDeregister()
/**
* Arrives at this phaser and deregisters from it without waiting
* for others to arrive. Deregistration reduces the number of
* parties required to advance in future phases. If this phaser
* has a parent, and deregistration causes this phaser to have
* zero parties, this phaser is also deregistered from its parent.
*
* <p>It is a usage error for an unregistered party to invoke this
* method. However, this error may result in an {@code
* IllegalStateException} only upon some subsequent operation on
* this phaser, if ever.
*
* @return the arrival phase number, or a negative value if terminated
* @throws IllegalStateException if not terminated and the number
* of registered or unarrived parties would become negative
*/
public int arriveAndDeregister() {
return doArrive(ONE_DEREGISTER);
}
调用该方法表明线程到达该相位器并注销自身,线程完成当前阶段的任务,不会等待其他线程到达。注销后将会减少后面阶段需要达到的参与者(任务)的数量。如何该相位器有父相位器,如果注销导致相位器的参与者数量减到0,那么该相位器也会从父相位器中注销。
未注册的参与者调用该方法是错误的,或许会抛出非法状态异常。该方法返回当前达到的阶段号,如果相位器已经终止则返回一个负值。如果相位器还没有终止且注册参与者的数量或者未到达的参与者数量是负值将会抛出非法状态异常。
线程同步控制
1、int arrive()
/**
* Arrives at this phaser, without waiting for others to arrive.
*
* <p>It is a usage error for an unregistered party to invoke this
* method. However, this error may result in an {@code
* IllegalStateException} only upon some subsequent operation on
* this phaser, if ever.
*
* @return the arrival phase number, or a negative value if terminated
* @throws IllegalStateException if not terminated and the number
* of unarrived parties would become negative
*/
public int arrive() {
return doArrive(ONE_ARRIVAL);
}
调用该方法表明线程到达这个相位器,也就是线程完成了当前阶段的任务,不会等待其他线程到达。未注册的参与者调用该方法是错误的。该方法返回当前到达的阶段号,或者返回一个负值如果相位器已经终止。
2、int arriveAndAwaitAdvance()
/**
* Arrives at this phaser and awaits others. Equivalent in effect
* to {@code awaitAdvance(arrive())}. If you need to await with
* interruption or timeout, you can arrange this with an analogous
* construction using one of the other forms of the {@code
* awaitAdvance} method. If instead you need to deregister upon
* arrival, use {@code awaitAdvance(arriveAndDeregister())}.
*
* <p>It is a usage error for an unregistered party to invoke this
* method. However, this error may result in an {@code
* IllegalStateException} only upon some subsequent operation on
* this phaser, if ever.
*
* @return the arrival phase number, or the (negative)
* {@linkplain #getPhase() current phase} if terminated
* @throws IllegalStateException if not terminated and the number
* of unarrived parties would become negative
*/
public int arriveAndAwaitAdvance() {
...
}
调用该方法表明线程已经达到相位器完成了当前阶段的任务,并等待其他线程全部到达并进入下一个阶段,返回的是下一个阶段号。和调用awaitAdvance(arrive())是等效的。
3、int awaitAdvance(int phase)
/**
* Awaits the phase of this phaser to advance from the given phase
* value, returning immediately if the current phase is not equal
* to the given phase value or this phaser is terminated.
*
* @param phase an arrival phase number, or negative value if
* terminated; this argument is normally the value returned by a
* previous call to {@code arrive} or {@code arriveAndDeregister}.
* @return the next arrival phase number, or the argument if it is
* negative, or the (negative) {@linkplain #getPhase() current phase}
* if terminated
*/
public int awaitAdvance(int phase) {
final Phaser root = this.root;
long s = (root == this) ? state : reconcileState();
int p = (int)(s >>> PHASE_SHIFT);
if (phase < 0)
return phase;
if (p == phase)
return root.internalAwaitAdvance(phase, null);
return p;
}
调用该方法线程将进入等待状态直到相位器进入到指定的阶段,如果当前阶段不等于指定的阶段或者相位器已经终止,那么会立刻返回。该方法返回下一个到达的阶段号(也就是指定的阶段号),参数phase的值通常是前面调用arrive()或者arriveAndDeregister()方法的返回值。
阶段终止
/**
* Overridable method to perform an action upon impending phase
* advance, and to control termination. This method is invoked
* upon arrival of the party advancing this phaser (when all other
* waiting parties are dormant). If this method returns {@code
* true}, this phaser will be set to a final termination state
* upon advance, and subsequent calls to {@link #isTerminated}
* will return true. Any (unchecked) Exception or Error thrown by
* an invocation of this method is propagated to the party
* attempting to advance this phaser, in which case no advance
* occurs.
*
* <p>The arguments to this method provide the state of the phaser
* prevailing for the current transition. The effects of invoking
* arrival, registration, and waiting methods on this phaser from
* within {@code onAdvance} are unspecified and should not be
* relied on.
*
* <p>If this phaser is a member of a tiered set of phasers, then
* {@code onAdvance} is invoked only for its root phaser on each
* advance.
*
* <p>To support the most common use cases, the default
* implementation of this method returns {@code true} when the
* number of registered parties has become zero as the result of a
* party invoking {@code arriveAndDeregister}. You can disable
* this behavior, thus enabling continuation upon future
* registrations, by overriding this method to always return
* {@code false}:
*
* <pre> {@code
* Phaser phaser = new Phaser() {
* protected boolean onAdvance(int phase, int parties) { return false; }
* };}</pre>
*
* @param phase the current phase number on entry to this method,
* before this phaser is advanced
* @param registeredParties the current number of registered parties
* @return {@code true} if this phaser should terminate
*/
protected boolean onAdvance(int phase, int registeredParties) {
return registeredParties == 0;
}
该方法是 Phaser 的关键回调方法,用于控制阶段转换时的行为逻辑。重写该方法可以在即将到达的下一个阶段之前执行一个动作,并控制阶段的终止。当所有参与者都到达当前阶段的屏障时该方法被自动调用。如果方法返回true,这个相位器将被设置成最终的终止状态;从源码可以看出,该方法的默认实现是直接判断参与者的数量是否为0,为0则返回true终止相位器;随后调用isTerminated()方法将返回true。如果要禁用这个默认实现,可以重写该方法返回false继续下一个阶段。
调用该方法产生的任何异常或者错误将会传播到其他试图到达该相位器的参与者中,在此情况下不会有推进阶段的发生。如果该相位器是一个多层结构的相位器,那么只有在根节点的相位器上调用该方法。
参数phase表示,调用该方法时当前的阶段号,也就是在这个相位器进入下一个阶段前的阶段号;参数registeredParties表示当前注册的参与者数量。如果相位器要终止了将返回true。
状态查询
1、int getPhase()
/**
* Returns the current phase number. The maximum phase number is
* {@code Integer.MAX_VALUE}, after which it restarts at
* zero. Upon termination, the phase number is negative,
* in which case the prevailing phase prior to termination
* may be obtained via {@code getPhase() + Integer.MIN_VALUE}.
*
* @return the phase number, or a negative value if terminated
*/
public final int getPhase() {
return (int)(root.state >>> PHASE_SHIFT);
}
调用该方法返回当前阶段编号(从 0 开始递增),最大值是Integer.MAX_VALUE。如果相位器已经终止,则返回一个负值,终止前的阶段号可以通过getPhase() + Integer.MIN_VALUE计算。
2、int getRegisteredParties()
/**
* Returns the number of parties registered at this phaser.
*
* @return the number of parties
*/
public int getRegisteredParties() {
return partiesOf(state);
}
该方法返回当前注册的参与者总数。
3、int getArrivedParties()
/**
* Returns the number of registered parties that have arrived at
* the current phase of this phaser. If this phaser has terminated,
* the returned value is meaningless and arbitrary.
*
* @return the number of arrived parties
*/
public int getArrivedParties() {
return arrivedOf(reconcileState());
}
该方法返回已到达当前阶段屏障的线程数,如果相位器已经终止了,那么返回值是没有意义的。
4、int getUnarrivedParties()
/**
* Returns the number of registered parties that have not yet
* arrived at the current phase of this phaser. If this phaser has
* terminated, the returned value is meaningless and arbitrary.
*
* @return the number of unarrived parties
*/
public int getUnarrivedParties() {
return unarrivedOf(reconcileState());
}
该方法返回尚未到达当前阶段屏障的线程数。
5、boolean isTerminated()
/**
* Returns {@code true} if this phaser has been terminated.
*
* @return {@code true} if this phaser has been terminated
*/
public boolean isTerminated() {
return root.state < 0L;
}
该方法判断相位器是否已经终止。
总结
本文详细讲解了Phaser的几类核心方法,方法比较多,我们用一个表格总结下:
类别 | 核心方法 | 应用场景 |
---|---|---|
构造函数 | Phaser(),Phaser(int parties),Phaser(Phaser parent),Phaser(Phaser parent, int parties) | 创建相位器实例 |
线程注册与注销 | int register(),int bulkRegister(int parties),int arriveAndDeregister() | 增加或者减少参与者 |
线程同步控制 | int arrive(),int arriveAndAwaitAdvance(),int awaitAdvance(int phase) | 线程阶段协同运行控制 |
阶段终止 | boolean onAdvance(int phase, int registeredParties) | 控制阶段转换时的行为逻辑 |
状态查询 | int getPhase(),int getRegisteredParties(),int getArrivedParties(),int getUnarrivedParties() | 监控相位器的运行状态 |
如果文章对您有帮助,不妨“帧栈”一下,您的肯定将是我写作的动力!