1

多くのスレッドから要求された書き込みアクションを収集し、それらをグループとして、たとえば 1 秒に 1 回フラッシュするバッファを Java で構築しています。waitForFlush次のフラッシュイベントが完了するまで、それをブロックして呼び出すメソッドと呼ばれるメソッドを提供したいと思います。その間、別のスタンドアロン スレッドがフラッシュし、ループ内でスリープします。だから私は基本的に、多くのスレッドが特定の時点でブロックし、それらをすべて同時に解放できるようにする同時実行構造またはパターンを探しています. . これまでに思いついたのは、次のように、wait/notifyAll です。

public class Buffer {

  private volatile long lastFlushTime = System.currentTimeMillis();
  private final Object flushMonitor = new Object();

  public void waitForFlush() {
    long entryTime = System.currentTimeMillis();

    synchronized(flushMonitor) {
      while(lastFlushTime <= entryTime) {
        flushMonitor.wait();
      }
    }
  }

  public void flush() {
    // do flush stuff here
    synchronized(flushMonitor) {
      lastFlushTime = System.currentTimeMillis();
      flushMonitor.notifyAll();
    }
  }
}

これは実際には問題なく機能すると思いますが、同期ブロックはwaitForNotify()まだ不完全に感じられます。理想的には、このユースケースでは、関連付けられたオブジェクトを同期せずに呼び出すことができ、ブロックされたすべてのスレッドが、同期されたブロックを 1 つずつ終了するのではなく、呼び出されwait()た瞬間に解放されます。notifyAll()1。

したがって、一般に、可変数のスレッドをブロックして同時に解放するより良い方法はありますか?

4

2 に答える 2

3

Marko Topolnikとmunyengmが言及しているように、CountDownLatchは1回限りのケースで機能しますが。周期的なシナリオでは失敗します (つまり、CDL ごとにawait& 1 回しかできません)。countDownその後、 CyclicBarrier を検討できますが、使用されているスレッドの数を知る必要があるため、このケースでは失敗します。

Java 7 を使用できる場合はPhaserをお勧めします。多くの待機中のスレッドに単一のスレッド シグナルを送信し、再利用することができます。

final Phaser phaser = new Phaser(1);//register one thread to arrive

 public void waitForFlush() {
    int phase = phaser.getPhase();
    phaser.awaitAdvance(phase);    
 }

  public void flush() {
      lastFlushTime = System.currentTimeMillis();
      phaser.arrive(); //signals all waiting threads on the current phase and will increment the phase by 1
  }
于 2012-07-07T14:33:19.057 に答える
2

をうまく使えば、あなたのためにCountDownLatchそれを行うことができると思います。方法は、ラッチで可変数のスレッドを作成awaitし、フラッシュスレッドがcountDown. ラッチは常に 1 に初期化されます。次のように動作します。

public class FlushControl
{
  private volatile CountDownLatch latch = new CountDownLatch(1);

  public void awaitFlush() throws InterruptedException { latch.await(); }

  public void flush() {
    final CountDownLatch l = latch;
    latch = new CountDownLatch(1);
    l.countDown();
  }
}
于 2012-07-07T14:25:41.040 に答える