4

すべての CountDownLatches を待機CountDownLatchContainer するメソッドを持つクラスを作成しました。await()すべてが正常に機能しています。

public final class CountDownLatchContainer
{
  private final Set<CountDownLatch> countDowns;

  public CountDownLatchContainer(List<CountDownLatch> countDowns)
  {
    this.countDowns = new HashSet<CountDownLatch>(countDowns);
  }

  public void await() throws InterruptedException
  {
    for (CountDownLatch count : countDowns)
      count.await();
  }
}

科学と芸術 (:D) のために、機能を拡張し、クラスpublic boolean await(long timeout, TimeUnit unit)からを追加したいと考えました。CountDownLatch

各カウントダウン ラッチに同じタイムアウトと全体的なメソッドを設定して、timeoutTimeUnits の数だけブロックするようにします。私はそれを達成するのに苦労しています。私が持っているものは次のとおりです。

  public boolean await(long timeout, TimeUnit unit) throws InterruptedException
  {
    boolean success = true;
    for (CountDownLatch count : countDowns)
      success &= count.await(timeout / countDowns.size(), unit);
    return success;
  }

そのため、全体のタイムアウトは処理されますが、各カウント ダウンは全体の時間の一部にすぎません。

では、合計時間を超えずに、メソッド パラメーターで指定されたのと同じ時間をシングル ラッチに与えるにはどうすればよいでしょうか。

ここで視覚化します。アスキーアートのインスピレーションのためのヘキサフラクションへのThx。

|-----------------------------|
             Total
|-----------------------------|
  L1       
|-----------------------------|
  L2       
|-----------------------------|
4

3 に答える 3

6

各ラッチを待ってから、残り時間を確認して作業します。

元の時間の最初のラッチを待つことから始めます。実際にかかった時間に注意してください。残り時間は合計からかかった時間を差し引いた値に設定されます。ここで、残り時間を制限して次のラッチを待ちます。実績を減算します。すべてのラッチが待機するか、残り時間が 0 になるまで続行します (ラッチが残り時間でタイムアウトになるため)。

|-----------------------------|
              Total
|------|----------------------|
  L1       Remaining(1)
|------|---------|------------|
  L1     L2        Remaining(2)

など... 合計を l1 待ち、残り (1) を l2 待ち、など

もう 1 つの方法は、操作を 1 ミリ秒ごとなどのスライスにタイムスライスすることです。ラッチをループし (使用済みとしてマークする/セットの変更可能なコピーの反復子を介してそれらを削除するのが適切な場合があります)、すべてのラッチが解放されるか、時間に達するまで、スライスの長さを待ちます。

于 2013-09-06T17:38:00.593 に答える
0

のノンブロッキング コンテナ バージョンを実装できたと思いますawait(long timeout, TimeUnit unit)

public final class CountDownLatchContainer {
    private final Set<CountDownLatch> countDowns;

    public CountDownLatchContainer(List<CountDownLatch> countDowns) {
        this.countDowns = new HashSet<CountDownLatch>(countDowns);
    }

    public void await() throws InterruptedException {
        for (CountDownLatch count : countDowns)
            count.await();
    }

    public boolean await(long timeout, TimeUnit unit)
            throws InterruptedException{
        boolean success = true;
        ExecutorService e = Executors.newFixedThreadPool(countDowns.size());
        List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(countDowns.size());

        for (CountDownLatch count : countDowns)
            futures.add(e.submit(new SingleLatchTimeOutAwaiter(count, timeout, unit)));

        for (Future<Boolean> f : futures) {
            try {
                success &= f.get();
            } catch (ExecutionException e1) {
                throw new InterruptedException();
            }
        }
        e.shutdown();
        return success;
    }

    private static class SingleLatchTimeOutAwaiter implements Callable<Boolean> {
        private final CountDownLatch count;
        private final long timeout;
        private final TimeUnit unit;

        private SingleLatchTimeOutAwaiter(CountDownLatch count, long timeout,
                TimeUnit unit) {
            this.count = count;
            this.timeout = timeout;
            this.unit = unit;
        }

        public Boolean call() throws Exception {
            return count.await(timeout, unit);
        }
    }
}

そして、ここにテストケースがあります。それはかなり正確です。

public class CountDownLatchContainerTest {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService e = Executors.newFixedThreadPool(3);
        CountDownLatch c1 = new CountDownLatch(1);
        CountDownLatch c2 = new CountDownLatch(1);

        CountDownLatchContainer c = new CountDownLatchContainer(Arrays.asList(
                c1, c2));
        e.submit(new MultiWaiter(c, 4, TimeUnit.SECONDS));
        Thread.sleep(1000);
        e.submit(new MultiWaiter(c, 2, TimeUnit.SECONDS));
        e.submit(new MultiWaiter(c, 3, TimeUnit.SECONDS));

        c1.countDown();
        int hundredth = 29; // 1/100 s delay
        for (int i = hundredth; i --> 0;) {
            Thread.sleep(100);
        }
        c2.countDown();
        e.shutdown();
    }

    private static class MultiWaiter implements Callable<Void> {
        private static final AtomicInteger instanceCounter = new AtomicInteger(
                0);
        private final int instance;

        private final CountDownLatchContainer c;
        private final long timeout;
        private final TimeUnit unit;

        private MultiWaiter(CountDownLatchContainer c, long timeout,
                TimeUnit unit) {
            this.c = c;
            this.timeout = timeout;
            this.unit = unit;
            this.instance = instanceCounter.getAndIncrement();
        }

        public Void call() throws Exception {
            System.out.println(getClass().getSimpleName() + "#" + instance
                    + " is waiting...");
            System.out.println(getClass().getSimpleName() + "#" + instance
                    + " is in time: " + c.await(timeout, unit));
            System.out.println(getClass().getSimpleName() + "#" + instance
                    + " is released!");
            return null;
        }
    }
}

出力

MultiWaiter#0 は待っています...

MultiWaiter#1 は待っています...
MultiWaiter#2 は待っています...



MultiWaiter#1 は間に合います: false
MultiWaiter#1 が解放されました!

MultiWaiter#0 is in time: true
MultiWaiter#0 が解放されました!
MultiWaiter#2 is in time: true
MultiWaiter#2 がリリースされました!

于 2013-09-06T22:36:02.667 に答える