CyclicBarrier(栅栏)的简单使用

①CyclicBarrier(栅栏),也就是可循环利用的屏障,可循环利用就是说该类创建的对象可以进行复用;屏障就是指每次线程运行时,都会碰到一个屏障,直到所有线程执行完毕,然后屏障才会才开,所有线程继续往下执行;CyclicBarrier是CountDownLatch的增强版本,增加了重置功能(通过其内部静态类Generation来实现重置功能)。
②CyclicBarrier的构造函数
(1)CyclicBarrier(int parties):parties(需要拦截的线程数)。
(2)CyclicBarrier(int parties, Runnable barrierAction):parties(表示需要拦截的线程数)、barrierAction(表示等待的线程中到达屏障是优先执行的Runnable对象)。
③CyclicBarrier(栅栏)的原理:内部定义了一个ReentrantLock(可重入得互斥锁)对象进行线程的,
④CyclicBarrier的API介绍:
1)Generation内部静态类(实现重置功能):
(1)源码:
(2)重置的方法:为CyclicBarrier实例中的域来重新创建一个新的Generation即可。

private static class Generation {
    //判断当前的屏障是否被打断了
     boolean broken = false;
}

(3)类的中内置属

    //所有方法的共享锁,可重入的互斥锁
    private final ReentrantLock lock = new ReentrantLock();
    //通过可重入的互斥锁得到的一个状态变量
    private final Condition trip = lock.newCondition();
    //总的等待线程的数量。
    private final int part   //屏障正常打开后优先运行的线程
    private final Runnable barrierCommand;
    //当前的Generation。每次屏障失效或者开闸之后,该独享都会自动被替换掉,从而实现重置的功能。
    private Generation generation = new Generation(); 

(4)await()方法
1)功能:调用该方法的线程会等待直到有足够数量的线程调用该方法(也就是我们说得开闸状态)
2)打破该状态的方法:
1、当最后一个线程到达。
2、有其他线程中断当前线程(抛出InterruptException异常)。
3、指定了限时操作,并到达时限时间(抛出TimeoutException异常)。
4、barrier被重置或屏障的地方处理打破状态(抛出BrokenBarrierException)。
3)两个需要锁的子方法

//在屏障开闸之后重置状态,以待下一次调用
private void nextGeneration() {
        // signal completion of last generation
        trip.signalAll();
        // set up next generation
        count = parties;
        generation = new Generation();
    }
    //实际上是在屏障打破之后设定打破状态(已唤醒其它线程并通知)
    private void breakBarrier() {
        generation.broken = true;
        count = parties;
        trip.signalAll();
    }

(5)reset()方法(重建屏障方法):
1)源码

  public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            breakBarrier();   //打破当前的屏障
            nextGeneration();//重新配置重置对象Generation
        } finally {
            lock.unlock();
        }  
     }   

2)注意点:只有先打破当前屏障,才能再重建一个新的屏障,否则可能导致信号丢失。

package com.atlihao.test;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;这里写代码片
import org.junit.jupiter.api.Test;
//高并发之栅栏
public class CyclicBarrierTest {
        @Test
        public void test1() {
            //并发线程数
            int count = 10000;
            CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
            //
            ExecutorService executorService = Executors.newFixedThreadPool(count-1);
            int n = 0;
            for (int i = 0; i < count; i++) {
                executorService.execute(new CyclicBarrierTest().new Task(cyclicBarrier, n));
                n++;
            }
            executorService.shutdown(); // 关闭线程池
            // 判断是否所有的线程已经运行完
            while (!executorService.isTerminated()) {
                try {
                    // 所有线程池中的线程执行完毕,执行后续操作
                    // TODO
                    System.out.println("==============is sleep============");
                    Thread.sleep(10000);
                    System.out.println("==============is wake============");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        public class Task implements Runnable {
            private CyclicBarrier cyclicBarrier;
            int n = 0;
            public Task(CyclicBarrier cyclicBarrier, int n) {
                this.cyclicBarrier = cyclicBarrier;
                this.n = n;
            }
            @Override
            public void run() {
                try {
                    // 等待所有任务准备就绪
                    System.out.println("选手" + n + "到达起跑线前");
                    cyclicBarrier.await();
                    System.out.println("选手" + n + "开始跑");
                    // 测试内容
                    System.out.println("hello: " + n);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
}

对CyclicBarrier(栅栏)的简单使用吧。

猜你喜欢

转载自blog.csdn.net/tree_ifconfig/article/details/81095256
今日推荐