2011-09-27 61 views
4

考慮:如何知道上次派對何時開始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),但在這種情況下如何使用它並不清楚。

回答

0

我想不出一種解決這個問題的非常優雅的方式,但是使用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); 
    } 
0

既然你似乎知道你有先驗多少任務,只需使用一個單獨的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

相關問題