我已经实现了从两个不同线程访问的 MyListener
。
class MyListener implements Listener {
private final Phaser phaser = new Phaser(2);
@Override
public void changed () {
phaser.arrive();
}
public void await () {
phaser.arriveAndAwaitAdvance();
}
}
我在主线程中这样使用它
MyListener listener = new Listener();
someObject.setListener(listener);
doSomething(); //it would result in Listener.changed() being invoked
listener.await();
doSomething(); //it would result in Listener.changed() being invoked
listener.await();
我有几个问题:
- Java 文档声明调用
arrive()
和arriveAndAwaitAdvance()
而不先调用register()
是不正确的。 changed()
可能会为同一事件调用多次。我预计await()
中的一个可能会因为之前的事件而立即返回。
对这个问题有什么想法吗?
最佳答案
关于您的第一个问题:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Phaser.html#arrive()
说:
It is a usage error for an unregistered party to invoke this method.
它没有声明必须通过调用 register()
来进行注册。像您一样在构造函数中指定预注册方的数量是一种有效的用法。
关于第二个,您不得多次调用arrive
。目前尚不清楚您为一个事件多次调用 changed()
的意图意味着什么,是否允许另一个线程在第一次调用时继续进行,最后一次调用(如何知道它是最后一个?)还是介于两者之间?
看来你想把到达分开,即给其他进程继续的权利,从等待这个许可。这很简单:不要使用复合 arriveAndAwaitAdvance()
:
int currentPhase = phaser.arrive(); // allow the other thread to proceed
…
phaser.awaitAdvance(currentPhase); // wait for the other thread’s arrival
关于java - 如何正确使用Phaser?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19561973/