CyclicBarrier

时间:2020-01-09 10:36:26  来源:igfitidea点击:

java.util.concurrent.CyclicBarrier类是一种同步机制,可以同步通过某种算法进行的线程。换句话说,这是所有线程必须继续等待直到所有线程到达它的屏障。

线程通过在CyclicBarrier上调用await()方法来互相等待。一旦N个线程在" CyclicBarrier"上等待,所有线程将被释放并可以继续运行。

创建一个CyclicBarrier

当创建一个" CyclicBarrier"时,我们指定释放它之前要等待多少个线程。这是创建" CyclicBarrier"的方法:

CyclicBarrier barrier = new CyclicBarrier(2);

在CyclicBarrier中等待

这是线程在CyclicBarrier中等待的方式:

barrier.await();

我们还可以为等待的线程指定超时。当超时时间过去后,即使不是所有的N个线程都在" CyclicBarrier"上等待,该线程也会被释放。这是我们指定超时的方法:

barrier.await(10, TimeUnit.SECONDS);

等待线程在CyclicBarrier处等待,直到:

  • 最后一个线程到达(调用await())
  • 该线程被另一个线程中断(另一个线程调用其interrupt()方法)
  • 另一个等待线程被中断
  • CyclicBarrier中等待时,另一个等待线程超时
  • 某些外部线程会调用" CyclicBarrier.reset()"方法。

循环屏障动作

" CyclicBarrier"支持屏障操作,这是一个" Runnable",在最后一个线程到达时执行。我们将" Runnable"屏障操作传递给其构造函数中的" CyclicBarrier",如下所示:

Runnable      barrierAction = ... ;
CyclicBarrier barrier       = new CyclicBarrier(2, barrierAction);

CyclicBarrier示例

这是一个代码示例,向我们展示如何使用CyclicBarrier

Runnable barrier1Action = new Runnable() {
    public void run() {
        System.out.println("BarrierAction 1 executed ");
    }
};
Runnable barrier2Action = new Runnable() {
    public void run() {
        System.out.println("BarrierAction 2 executed ");
    }
};

CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);

CyclicBarrierRunnable barrierRunnable1 =
        new CyclicBarrierRunnable(barrier1, barrier2);

CyclicBarrierRunnable barrierRunnable2 =
        new CyclicBarrierRunnable(barrier1, barrier2);

new Thread(barrierRunnable1).start();
new Thread(barrierRunnable2).start();

这是CyclicBarrierRunnable类:

public class CyclicBarrierRunnable implements Runnable{

    CyclicBarrier barrier1 = null;
    CyclicBarrier barrier2 = null;

    public CyclicBarrierRunnable(
            CyclicBarrier barrier1,
            CyclicBarrier barrier2) {

        this.barrier1 = barrier1;
        this.barrier2 = barrier2;
    }

    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() +
                                " waiting at barrier 1");
            this.barrier1.await();

            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() +
                                " waiting at barrier 2");
            this.barrier2.await();

            System.out.println(Thread.currentThread().getName() +
                                " done!");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

这是执行上述代码的控制台输出。请注意,线程执行写入控制台的顺序可能因执行而异。有时会先显示"线程-0",有时会先打印" Thread-1",依此类推。

Thread-0 waiting at barrier 1
Thread-1 waiting at barrier 1
BarrierAction 1 executed
Thread-1 waiting at barrier 2
Thread-0 waiting at barrier 2
BarrierAction 2 executed
Thread-0 done!
Thread-1 done!