如何知道上次派对何时开始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);
}
};
我不认为你的代码应该检查'if(registeredParties == 0)',因为'onAdvance()'保证只在所有各方到达后才被调用。无论是否有0方等待或更多,该事件应该会触发。 – Gili
很对,编辑。 – rxg