Java并发编程之java.util.concurrent包——CyclicBarrier篇

概念

  • 从字面上的意思可以知道,这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。

  • 它的作用就是会让所有线程都等待完成后才会继续下一步行动。

  • 举个例子,就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。

构造方法

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

解析:

  • parties 是参与线程的个数
  • 第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务

重要方法

public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException

解析:

  • 线程调用 await() 表示自己已经到达栅栏
  • BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时

下面我们就来自定义实现一个CyclicBarrier

代码如下:

public class KaneCyclicBarrier {
    
    

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    private int count =0; //批次

    private final int parties; //多少线程准备就绪?

    private Object generation = new Object();

    public KaneCyclicBarrier(int parties) {
    
    
        this.parties = parties;
    }



    public  void await(){
    
    
        final ReentrantLock lock = this.lock;
        lock.lock();
       try {
    
    
            final  Object g = generation;

           int index = ++count;
           if (index == parties) {
    
    
             nextGeneration();
             return;
           }

           while (true) {
    
    
               try {
    
    
                   condition.await();
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
               }

               if(g!=generation){
    
    
                   return;
               }
           }
       }finally {
    
    
           lock.unlock();
       }
    }

    public void nextGeneration(){
    
    
        condition.signalAll();
        count=0;
        generation = new Object();
    }
}

测试一下,代码如下:

public class CyclicBarrier_Demo {
    
    
    public CyclicBarrier_Demo() {
    
    
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        KaneCyclicBarrier barrier = new KaneCyclicBarrier(4);

        for(int i = 0; i < 100; ++i) {
    
    //假设有100个任务,每次只能有固定数量的线程去执行,可以使用这个
            (new Thread(() -> {
    
    
                barrier.await();
                System.out.println("任务开始执行");
            })).start();
            Thread.sleep(500L);
        }

    }
}

CyclicBarrier 使用场景

可以用于多线程计算数据,最后合并计算结果的场景。

CyclicBarrier 与 CountDownLatch 区别

  • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
  • CountDownLatch减计数,CyclicBarrier加计数。
  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。

猜你喜欢

转载自blog.csdn.net/Number_oneEngineer/article/details/119383575
今日推荐