CyclicBarrier使用 栅栏

 

/*该类的说明

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。

CyclicBarrier barrier = new CyclicBarrier(str.length, new RunnableLast());第一个参数值 
为这个屏障点

在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。

因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

使用场景

需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用CyclicBarrier。

CyclicBarrier 类构造函数CyclicBarrier(int parties)有一个整数初始值,这个值表示将在同一个点需要同步的线程数量。

当其中一个线程到达某个阶段点后,它会调用await() 方法来等待其他线程。调用这个方法后,CyclicBarrier阻塞线程进入休眠直到

其他线程到达。当最后一个线程调用CyclicBarrier 类的await() 方法,它唤醒所有等待的线程并继续执行它们的任务。然后如此循环。 
CyclicBarrier 类的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction)初始时还可带一个Runnable的参数,

此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。

常用方法说明

CyclicBarrier(int parties) 创建一个新的CyclicBarrier,parties表示有多少个数量的参与者参与。

CyclicBarrier(int parties, Runnable barrierAction) 创建一个新的CyclicBarrier,parties表示有多少个数量的参与者参与。barrierAction会由最后一个进入 barrier 的参与者执行。

int await() 在所有参与者在调用 await方法之前,将一直等待。

int await(long timeout, TimeUnit unit) 在等待时间超过timeout之前,所有参与者在调用 await方法之前,将一直等待。unit表示等待时间的单位。

int getNumberWaiting() 返回当前在屏障处等待的参与者数目。int getParties() 返回要求启动此barrier的参与者数目。

boolean isBroken() 查询此屏障是否处于损坏状态。

void reset() 将屏障重置为其初始状态。


*/




package test.data.com.cyclicbarrier;

import com.alibaba.fastjson.*;
import org.apache.logging.log4j.*;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author HUAZAI
 * @title:
 * @description:
 * @return 返回类型 :
 * <ul>
 * <li></li>
 * <li></li>
 * <ul>
 * @throws
 * @date 18-4-11 下午3:21
 */
public class RunnableTest implements Runnable {
    private static final Logger logger = LogManager.getLogger(RunnableTest.class);
    private Integer num;
    private CyclicBarrier cyclicBarrier;
    private String name;

    public RunnableTest(Integer num, CyclicBarrier cyclicBarrier, String name) {
        this.num = num;
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        logger.info(
                this.name + " 已经到了 " + " 他是第 " + (cyclicBarrier.getNumberWaiting() + 1) + " 个到的");
        logger.info(JSON.toJSONString(cyclicBarrier));
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            logger.error(" =========== ", e);
        } catch (BrokenBarrierException e) {
            logger.error(" =========== ", e);
        }
        try {
            Thread.sleep(1000 * ((new Random()).nextInt(7)));
        } catch (InterruptedException e) {
            logger.error(" =========== ", e);
        }
        logger.info(this.name + " 已经到了 所有人已经到齐 一共 " + (cyclicBarrier.getParties()) + " ");
    }
}
package test.data.com.cyclicbarrier;

import org.apache.logging.log4j.*;

/**
 * @author HUAZAI
 * @title:
 * @description:
 * @return 返回类型 :
 * <ul>
 * <li></li>
 * <li></li>
 * <ul>
 * @throws
 * @date 18-4-11 下午3:30
 */
public class RunnableLast implements Runnable {
    private static final Logger logger = LogManager.getLogger(RunnableLast.class);

    @Override
    public void run() {
        logger.info("所有人一起去 Happy Go");
    }
}

 
    
package test.data.com.cyclicbarrier;

import java.util.concurrent.*;

/**
 * @author HUAZAI
 * @title:
 * @description:
 * @return 返回类型 :
 * <ul>
 * <li></li>
 * <li></li>
 * <ul>
 * @throws
 * @date 18-4-11 下午3:17
 */
public class MyCyclicBarrier {
    public static void testRun(CyclicBarrier barrier, String... name) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        for (int index = 0, size = name.length; index < size; index++) {
            RunnableTest runnableTest = new RunnableTest(index, barrier, name[index]);
            executorService.execute(runnableTest);
            Thread.sleep(1000);//此处如果不进行睡眠操作  会使得cyclicBarrier.getNumberWaiting() 乱掉 并发导致
        }
        executorService.shutdown();
    }
}

package test.data.com.main;

import org.apache.logging.log4j.*;
import test.data.com.cyclicbarrier.*;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author LIUHUA
 * @title:
 * @description:
 * @return 返回类型 :
 * <ul>
 * <li></li>
 * <li></li>
 * <ul>
 * @throws
 * @date 18-4-2 上午11:42
 */
public class MainTest {
    private static final org.apache.logging.log4j.Logger logger1 = org.apache.logging.log4j.LogManager.getLogger(MainTest.class);

    public static void main(String[] args) {
//        testLogger();
        String[] str = {"华仔1","华仔2","华仔3","华仔4","华仔5"};
        CyclicBarrier barrier = new CyclicBarrier(str.length, new RunnableLast());
        try {
            MyCyclicBarrier.testRun(barrier, str);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 

执行结果

华仔1 已经到了  他是第 1 个到的  如果在MyCyclicBarrier的for中不加sleep 会导致第几个到的数据不准确
{"broken":false,"numberWaiting":0,"parties":5}
华仔2 已经到了  他是第 2 个到的
{"broken":false,"numberWaiting":1,"parties":5}
华仔3 已经到了  他是第 3 个到的
{"broken":false,"numberWaiting":2,"parties":5}
华仔4 已经到了  他是第 4 个到的
{"broken":false,"numberWaiting":3,"parties":5}
华仔5 已经到了  他是第 5 个到的
{"broken":false,"numberWaiting":4,"parties":5}
所有人一起去 Happy Go
华仔4 已经到了 所有人已经到齐 一共 5 人
华仔3 已经到了 所有人已经到齐 一共 5 人
华仔2 已经到了 所有人已经到齐 一共 5 人
华仔5 已经到了 所有人已经到齐 一共 5 人

华仔1 已经到了 所有人已经到齐 一共 5 人

MyCyclicBarrier的for中不加sleep 会导致第几个到的数据不准确 结果如下

华仔2 已经到了  他是第 1 个到的
华仔3 已经到了  他是第 1 个到的
华仔4 已经到了  他是第 1 个到的
华仔5 已经到了  他是第 1 个到的
华仔1 已经到了  他是第 1 个到的
{"broken":false,"numberWaiting":0,"parties":5}
{"broken":false,"numberWaiting":0,"parties":5}
{"broken":false,"numberWaiting":2,"parties":5}
{"broken":false,"numberWaiting":3,"parties":5}
{"broken":false,"numberWaiting":3,"parties":5}
所有人一起去 Happy Go
华仔2 已经到了 所有人已经到齐 一共 5 人
华仔1 已经到了 所有人已经到齐 一共 5 人
华仔3 已经到了 所有人已经到齐 一共 5 人
华仔5 已经到了 所有人已经到齐 一共 5 人
华仔4 已经到了 所有人已经到齐 一共 5 人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值