Skip to content

Latest commit

 

History

History
110 lines (57 loc) · 6.06 KB

chapter06.md

File metadata and controls

110 lines (57 loc) · 6.06 KB

运行分为多阶段的任务:Phaser 类

在 Java 7 中,并发 API 引入了 Phaser 类。该类提供了一种强大的机制(分段器),将任务划分为多个阶段执行。任务可以要求 Phaser 类等待直到所有其他参与方完成该阶段。

Phaser 类简介

Phaser 类是一种同步机制,用于控制以并发方式划分为多个阶段的算法的执行。如果处理过程已有明确定义的步骤,那么必须在开始第二个步骤之前完成第一步的工作,以此类推,并且可以使用 Phaser 类实现该过程的并发版本。Phaser 类的主要特征有以下几点。

  • phaser 必须知道要控制的任务数。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 值。

关键字抽取算法

要实现的算法将通过执行下述阶段计算文档集合中的最佳关键字。

  • 阶段 1:解析所有文档并且抽取所有单词的 DF 值。只有解析了所有文档才可以获得准确值。
  • 阶段 2:计算所有文档中单词的 TF-IDF 值。为每个文档选择 10 个关键字(TF-IDF 值评价最高的 10 个单词)。
  • 阶段 3:获得一个最佳关键字列表。这个列表中的单词应该能够代表大多数文档的关键字。

★ 小结

Phaser 的主要目的是为执行分为多阶段的算法的任务提供同步。在所有任务都完成上一阶段之前,任何任务都不能开始执行下一阶段。

分段器必须知道任务要进行同步的任务数量。必须使用构造方法、bulkRegister() 方法或 register() 方法在分段器中注册任务。

分段器可以以不同方式同步任务。最常见的方式是使用 arriveAndAwaitAdvance() 方法告诉分段器,任务已经完成了一个阶段的执行,要继续执行下一阶段。该方法将休眠该线程直到剩下的任务都完成当前阶段为止。

arrive() 方法用于通知分段器当前阶段已经完成,但是不会等待剩下的任务。

arriveAndDeregister() 方法用于告知分段器当前阶段已经完成,而且并不想在分段器中继续等待,通常是因为已经完成了任务。

awaitAdvance() 方法可用于等待指定阶段结束。