如何知道上次派对何时开始Phaser.arrive()?

问题描述:

考虑:如何知道上次派对何时开始Phaser.arrive()?

Executor executor = ...; 
Phaser phaser = new Phaser(n); 
for (int i=0; i<n; ++i) 
{ 
    Runnable task = new Runnable() 
    { 
    public void run() 
    { 
     phaser.arriveAndDeregister(); 
     if (lastTask) 
     doSomething(this); 
    } 
    } 

    // run tasks using a thread-pool (order is not guaranteed) 
    executor.submit(task); 
} 

我想看看我的最后一个任务,以火doSomething()这取决于任务的内部状态。我发现Phaser.onAdvance(int, int),但在这种情况下如何使用它并不清楚。

我想不出一种解决这个问题的非常优雅的方式,但是使用ThreadLocal和onAdvance可以提供帮助。

final ThreadLocal<Boolean> isLast = new ThreadLocal<Boolean>() { 
     public Boolean initialValue() { 
      return false; 
     } 
    }; 
    final Phaser p = new Phaser(9) { 
     public boolean onAdvance(int phase, int registeredParties) { 
      isLast.set(true); 
      return true; 
     } 
    }; 

然后

public void run() 
    { 
     phaser.arriveAndDeregister(); 
     if (isLast.get()) 
     doSomething(this); 
    } 

既然你似乎知道你有先验多少任务,只需使用一个单独的AtomicInteger

int n = 5; 
ExecutorService executor = ... 
final AtomicInteger count = new AtomicInteger (n); 
final Phaser phaser = new Phaser (n); 
for (int i = 0; i < n; ++i) { 
    Runnable task = new Runnable() { 
     public void run() { 
      phaser.arriveAndDeregister(); 
      if (count.decrementAndGet() == 0) { 
       doSomething (this); 
      } 
     } 
    }; 

    // run tasks using a thread-pool (order is not guaranteed) 
    executor.submit (task); 
} 

或者,如果你需要调用doSomething通知当事人休眠之前,恰好覆盖onAdvance,并从那里做。

final Phaser phaser = new Phaser (n) { 
    protected boolean onAdvance(int phase, int registeredParties) { 
     doSomething(this); 

     return super.onAdvance(phase, registeredParties); 
    } 
}; 
+0

我不认为你的代码应该检查'if(registeredParties == 0)',因为'onAdvance()'保证只在所有各方到达后才被调用。无论是否有0方等待或更多,该事件应该会触发。 – Gili

+0

很对,编辑。 – rxg