当前位置:嗨网首页>书籍在线阅读

21-结果分析

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

结果分析

该案例在一开始便创建了 Phaser 对象,以便在每个阶段结束时对多线程同步。 Phaser 类的构造器接收的参数代表参与同步的任务数,在本案例中,共有3个线程作为同步参与者。这个参数意味着,在 Phaser 进入下一阶段并唤醒休眠线程前,应该有3个线程调用 arriveAndAwaitAdvance() 方法。

创建完毕 Phaser 对象后,启动3个线程分别执行3个不同的 FileSearch 任务。

本案例使用了Windows操作系统下的路径。如果使用其他操作系统,请调整为对应系统中存在的一个路径,比如 `/var/log` ,或者类似的路径。

FileSearch 对象的 run() 方法中,第一步就调用了 Phaser 对象的 arriveAnd- AwaitAdvance() 方法。正如前文所述, Phaser 对象中记录着需要同步的线程数。当一个线程调用该方法时, Phaser 对象将当前阶段需要等待的线程数减1,并使调用线程休眠,直到所有线程均已完成当前阶段的任务。在 run() 方法开始时调用该方法,可以确保在所有线程都创建完毕后,才开始执行搜索任务。

在第一阶段和第二阶段结束前,检查了该阶段是否生成了包含元素的结果列表。如果包含元素,则 checkResults() 方法调用之前解释过的 arriveAndAwaitAdvance() 方法;如果结果列表为空,则已经没有继续查找的意义,线程结束执行。需要注意的是,在第二种情况中,可以用 arriveAndDeregister() 方法通知 Phaser 对象来减少一个参与同步的线程。这并意味着该调用线程不再参与将来其他阶段的任务, Phaser 对象也不会再同步等待该线程。

第三阶段的 showInfo() 方法调用了 Phaser 对象的 arriveAndAwaitAdvance() 方法。这个方法能够保证所有线程同时完成。在 showInfo() 方法结束后,程序调用了 Phaser 对象的 arriveAndDeregister() 方法。该方法将从 Phaser 对象上注销一个同步参与线程,正如前文所述,当所有线程结束时, Phaser 对象上将有0个同步参与者。

最后, main() 方法等待3个同步线程执行完毕,并调用 Phaser 对象的 isTerminated() 方法。当一个 Phaser 对象上只剩0个同步参与者时, Phaser 对象进入一个终止状态(Termination),并且 isTerminated() 方法会返回 true 。因为在搜索完成后注销了 Phaser 对象上的所有参与者,所以 Phaser 对象处于终止状态,调用该方法会在控制台输出 true

Phaser 对象有两种状态。

  • Active: Phaser 在接受新参与者注册及每个阶段结束后同步时,便进入该状态。在该状态下, Phaser 以本节介绍的方式进行工作。`在Java API中,未明确提出该状态。
  • Termination:Phaser 的所有参与者都注销时,默认就会进入终止状态。更进一步说,是 PhaseronAdvance() 方法在参与者数量为0时,返回了 true ,该方法返回 true 就会导致 Phaser 进入终止状态。可以重写该方法来修改这种默认行文。当 Phaser 处于该状态时,同步方法 arriveAndAwaitAdvance() 将立即返回,不会有任何同步操作。

Phaser 类有个显著的特点是与其相关的方法均不需要进行异常处理。与其他同步工具类不同,由 Phaser 休眠的线程不会响应中断,也不会抛出中断异常。在下一节中,将介绍其仅有的一个异常。

案例运行结果如下图所示:

29.png 上图显示了前两个阶段的执行过程。可以看到 Apps 线程在第二阶段,因为结果列表为空而终止。运行该案例可以发现即便一些线程比其他线程提前结束一个阶段,也仍须等待其他线程全部结束该阶段,才能继续执行。