Phaser是jdk7中新增的并发同步器,具有CyclicBarrier和CountDownLatch的功能,但比后两者更灵活。
CyclicBarrier和CountDownLatch的特点是parties数(参与控制计数的线程数)是固定的,是在这两个同步器的构造方法参数中指定的。
CyclicBarrier和CountDownLatch的区别是:
使用CyclicBarrier:当await()时,线程计数加一,同时该线程阻塞,直到所有parties个线程都到达,然后所有线程同时解除阻塞。
使用CountDownLatch:当countDown()时,线程计数减一,但该线程不阻塞,而是另外的调用CountDownLatch.await()的线程阻塞,当线程计数减到0时,阻塞的线程解除阻塞。
Phaser登场:
Phaser与CyclicBarrier.await()对应的方法是arriveAndAwaitAdvance()。与CountDownLatch.countDown()对应的方法是arrive()。与CountDownLatch.await()相对于的方法是awaitAdvance(int phase)。(awaitAdvance方法相比CountDownLatch.await()多个参数,后面会讲)
Phaser独特的功能是parties数可动态改变,通过register()和arriveAndDeregister()来增减。
Phaser有一个独特的概念是phase,默认是0,当getRegisteredParties()个parties都arrive了,phase即升级为1,依次类推,2、3...。直观上理解,phase每升一次级,相当于Phaser重生,只是phase号加一了而已。如果你在一个线程或多个线程中不断的调用arrive(),那么会发现getArrivedParties()值不断的增长,当长到getRegisteredParties()值时,你会发现phase自动升级了,同时getArrivedParties()恢复为0。
你可以重写onAdvance(...)方法,该方法在phase升级时会得到回调,方法签名及默认实现为:
protected boolean onAdvance(int phase, int registeredParties) {
return registeredParties == 0;
}
当返回值为true时,表示你想让该Phaser结束。
awaitAdvance(int phase)的签名为:
public int awaitAdvance(int phase)
phase参数很重要,想要这个方法起作用,phase必须等于当前phase号,否则该方法直接返回。
该方法的返回值为升级后的phase号,或一个负数(表示Phaser已结束)