我已经实现了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()

    说:



    它没有声明必须通过调用register()进行注册。与您一样在构造函数中指定预注册方的数量是一种有效用法。

    关于第二个,您不得多次调用arrive。目前尚不清楚您为一个事件多次调用changed()的意图意味着什么,是否允许另一个线程在第一次调用,最后一个调用(如何知道它是最后一个?)或两者之间进行?

    看来您想从等待此权限中拆分到达权限,即赋予其他进程继续执行的权限。这很容易:不要使用复合arriveAndAwaitAdvance():

    int currentPhase = phaser.arrive(); // allow the other thread to proceed
    …
    phaser.awaitAdvance(currentPhase); // wait for the other thread’s arrival
    

    09-26 06:46