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 返回类型 :
 * 
    *
  • *
  • *
      * @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 返回类型 :
 * 
    *
  • *
  • *
      * @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 返回类型 :
 * 
    *
  • *
  • *
      * @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 返回类型 :
 * 
    *
  • *
  • *
      * @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 人

你可能感兴趣的:(java编程方法总结)