1

口で言うだけなら簡単です。コードを表示します。

MyCyclicBarrier.java

public class MyCyclicBarrier extends Thread{
    private CyclicBarrier cyclicBarrier;

    public MyCyclicBarrier(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println("Thread start." + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(2);  //biz code
            System.out.println("Thread "+Thread.currentThread().getName()+" is waiting for the other Threads."+
                    "\n\t\t\t\tIt's parties is "+cyclicBarrier.getParties()+
                    "\n\t\t\t\tWaiting for "+cyclicBarrier.getNumberWaiting()+" Threads");
            cyclicBarrier.await(3,TimeUnit.SECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
            e.printStackTrace();
        }
        System.out.println("Thread end."+Thread.currentThread().getName());
    }
}

TestCyclicbarrier.java

public class TestCyclicbarrier1 {
    public static void main(String[] args) {
        int length = 5;
        long start = System.currentTimeMillis();
        CyclicBarrier cyclicBarrierWithRunnable = new CyclicBarrier(length, () -> {
            System.out.println("the final reach Thread is " + Thread.currentThread().getName());
            long end = System.currentTimeMillis();
            System.out.println("cost totally :" + (end - start) / 1000 + "s");
        });
        for (int i = 0; i < length; i++) {
            if (i != 4) {
                new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
            } else {
                try {
                    TimeUnit.SECONDS.sleep(2);
                    new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力:

Thread start.Thread-1
Thread start.Thread-0
Thread start.Thread-2
Thread start.Thread-3
Thread Thread-0 is waiting for the other Threads.
                It's parties is 5
                Waiting for 0 Threads
Thread Thread-3 is waiting for the other Threads.
                It's parties is 5
                Waiting for 0 Threads
Thread start.Thread-4
Thread Thread-1 is waiting for the other Threads.
                It's parties is 5
                Waiting for 0 Threads
Thread Thread-2 is waiting for the other Threads.
                It's parties is 5
                Waiting for 1 Threads
Thread Thread-4 is waiting for the other Threads.
                It's parties is 5
                Waiting for 4 Threads
the final reach Thread is Thread-4
cost totally :4s
Thread end.Thread-4
Thread end.Thread-0
Thread end.Thread-3
Thread end.Thread-2
Thread end.Thread-1

ネットでずっと探しています。しかし、同様の答えはありません。助けてください、またはいくつかのアイデアを提供してみてください! そして、私は学び始めたところCyclicBarrierです。

私は誤解したのだろうかCyclicBarrier.await(int timeout,TimeUnit unit)。スレッド 0 から 3 は、すでに 2 秒かかるバリア ポイントに到達しています。同時に、2 秒待機した後に最後のスレッドが開始されました。ここに質問があります: なぜここでCyclicBarrier.await(int timeout, TimeUnit unit) 投げなかったのTimeOutExceptionですか?

4

2 に答える 2

0

スレッド 0 から 3 は、コスト 2 のバリア ポイントに既に到達しています。

正解です。

同時に、2 秒間待機した後に最後のスレッドが開始されました。

正しい。このスレッドが開始されるまでに、他の 4 つのスレッドが CB を待機していることに注意してください (3 秒のタイムアウト、つまり、発生するまで 3 秒ありTimeoutExceptionます)。

しかし、スレッド 4 はメソッド内で 2 秒間しかスリープしませんrun(メソッドまではまだ 1 秒しかありませんTimeoutException)。

になるとawait、それは最後のスレッドなので、もう待つ必要はありません。したがって、バリアアクションが実行され、他のアクションはブロック解除されます-javadocから、

現在のスレッドが到着する最後のスレッドであり、null 以外のバリア アクションがコンストラクターで指定された場合、現在のスレッドは、他のスレッドの続行を許可する前にアクションを実行します。

スレッド 4 を開始する前に 4 秒間スリープ状態にすると、TimeoutException.

try {
    TimeUnit.SECONDS.sleep(4);
    new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
} catch (InterruptedException e) {
     e.printStackTrace();
}
于 2021-06-19T09:43:02.867 に答える