TL; DR:在该上下文中使用Phaser.arriveAndDeregister()
为非阻塞信号到移相器,其对应于操作CountDownLatch.countDown()
的服务员。
Phaser
和CountDownLatch
。澄清的第一件事是,Phaser
不能通常编码CountDownLatch
。用Phaser
同步的任务都必须等待对方(所有到所有同步)。在CountDownLatch
中,有一组任务等待一些其他任务来打开锁存器。
Phaser
和CyclicBarrier
。这两种机制都用于全部同步。它们之间的两个区别是:1)一个Phaser
使用相位器的一组任务可能会在相位器的生命周期中增长,而在CyclicBarrier
中,参与者的数量是固定; 2)与Phasers
,任务可以通知其他成员(参与者),并且不等待,只要它从该相位器注销,而使用循环屏障的所有任务只能等待并通知。
使用Phaser
编码CountDownLatch
。要编码的CountDownLatch(1)你需要牢记以下移相器:注册政党的数量,或者通过new Phaser(PARTIES_COUNT)
或通过Phaser.register
:
- 缔约方数量=服务员+ 1的号码。
CountDown.await()
= Phaser.arriveAndAwaitAdvance()
CountDown.countDown()
= Phaser.arriveAndDeregister()
实施例。假设您希望子任务等待父任务信号。使用CountDownLatch
你可以这样写:
import java.util.concurrent.*;
class CountDownExample {
public static void main(String[] args) throws Exception {
CountDownLatch l = new CountDownLatch(1);
new Thread(() -> {
try {
l.await();
System.out.println("Child: running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
System.out.println("Parent: waiting a bit.");
Thread.sleep(100);
l.countDown();
}
}
使用Phaser
你可以这样写:
import java.util.concurrent.*;
class PhaserExample {
public static void main(String[] args) throws Exception {
Phaser ph = new Phaser(2); // 2 parties = 1 signaler and 1 waiter
new Thread(() -> {
ph.arriveAndAwaitAdvance();
System.out.println("Child: running");
}).start();
System.out.println("Parent: waiting a bit.");
Thread.sleep(100);
ph.arriveAndDeregister();
}
}
你可能想看看this post for another example。
这是不正确的 - 你的榜样,你认为是侍应生数提前,这是不是在COuntdownLatch的情况是已知的,该解决方案是不是一个通用的一个 – Bober02
的一点是,有没有**一般编码**使用juc.Phasers编码CountdownLatches。所以要么a)我们牺牲表现力并引入争用(通过选择全部同步),或者我们需要事先知道多少参与者并获得相同的争用水平。 –
我已更新文字以反映上述讨论。 –