• java多线程-CyclicBarrier


    • 介绍

      一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 

      CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 

    • 主要方法
    • 1 //设置parties、count及barrierCommand属性。   
      2 CyclicBarrier(int):   
      3 //当await的数量到达了设定的数量后,首先执行该Runnable对象。   
      4 CyclicBarrier(int,Runnable):   
      5 //通知barrier已完成线程   
      6 await():  
    • 应用场景

      1:CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在i指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐。

      代码:

     1 public class CyclicBarrierTest {
     2     public static void main(String[] args){
     3         ExecutorService pool = Executors.newCachedThreadPool();
     4         final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
     5         
     6         for (int i = 0; i < 3; i++) {
     7             Runnable runnable = new Runnable() {
     8                 @Override
     9                 public void run(){
    10                     try {
    11                         Thread.sleep(new Random().nextInt(5000));
    12                     } catch (InterruptedException e) {
    13                         // TODO Auto-generated catch block
    14                         e.printStackTrace();
    15                     }
    16                     System.out.println(Thread.currentThread().getName()+"到达地点一,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
    17                     try {
    18                         cyclicBarrier.await();//障碍等待点
    19                     } catch (InterruptedException e) {
    20                         // TODO Auto-generated catch block
    21                         e.printStackTrace();
    22                     } catch (BrokenBarrierException e) {
    23                         // TODO Auto-generated catch block
    24                         e.printStackTrace();
    25                     }
    26                     try {
    27                         Thread.sleep(new Random().nextInt(5000));
    28                     } catch (InterruptedException e) {
    29                         // TODO Auto-generated catch block
    30                         e.printStackTrace();
    31                     }
    32                     System.out.println(Thread.currentThread().getName()+"到达地点二,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
    33                     try {
    34                         cyclicBarrier.await();//障碍等待点
    35                     } catch (InterruptedException e) {
    36                         // TODO Auto-generated catch block
    37                         e.printStackTrace();
    38                     } catch (BrokenBarrierException e) {
    39                         // TODO Auto-generated catch block
    40                         e.printStackTrace();
    41                     }
    42                     try {
    43                         Thread.sleep(new Random().nextInt(5000));
    44                     } catch (InterruptedException e) {
    45                         // TODO Auto-generated catch block
    46                         e.printStackTrace();
    47                     }
    48                     System.out.println(Thread.currentThread().getName()+"到达地点三,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"人齐了出发":"继续等待"));
    49                     try {
    50                         cyclicBarrier.await();//障碍等待点
    51                     } catch (InterruptedException e) {
    52                         // TODO Auto-generated catch block
    53                         e.printStackTrace();
    54                     } catch (BrokenBarrierException e) {
    55                         // TODO Auto-generated catch block
    56                         e.printStackTrace();
    57                     }
    58                 }
    59             };
    60             pool.execute(runnable);
    61         }
    62         pool.shutdown();
    63     }
    64 }

      执行结果:

    1 pool-1-thread-3到达地点一,当前等待人数为1继续等待
    2 pool-1-thread-1到达地点一,当前等待人数为2继续等待
    3 pool-1-thread-2到达地点一,当前等待人数为3继续出发
    4 pool-1-thread-1到达地点二,当前等待人数为1继续等待
    5 pool-1-thread-3到达地点二,当前等待人数为2继续等待
    6 pool-1-thread-2到达地点二,当前等待人数为3继续出发
    7 pool-1-thread-3到达地点三,当前等待人数为1继续等待
    8 pool-1-thread-2到达地点三,当前等待人数为2继续等待
    9 pool-1-thread-1到达地点三,当前等待人数为3人齐了出发
    View Code

      2:在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。

      代码:

     1 public class CyclicBarrierTest1 {
     2     public static void main(String[] args) {
     3         ExecutorService threadPool = Executors.newCachedThreadPool();
     4         CyclicBarrier barrier = new CyclicBarrier(5, new mainTask());
     5         for (int i = 0; i < 5; i++) {
     6             subTask subTask = new subTask(barrier);
     7             threadPool.execute(subTask);
     8         }
     9         threadPool.shutdown();
    10     }
    11 }
    12 
    13 class subTask implements Runnable{
    14     private CyclicBarrier barrier;
    15     
    16     public subTask(CyclicBarrier barrier) {
    17         super();
    18         this.barrier = barrier;
    19     }
    20     @Override
    21     public void run() {
    22         System.out.println(Thread.currentThread().getName()+"正在执行");
    23         try {
    24             Thread.sleep(5000);
    25         } catch (InterruptedException e) {
    26             // TODO Auto-generated catch block
    27             e.printStackTrace();
    28         }
    29         System.out.println(Thread.currentThread().getName()+"执行完毕,等待其他结果");
    30         try {
    31             barrier.await();
    32         } catch (InterruptedException e) {
    33             // TODO Auto-generated catch block
    34             e.printStackTrace();
    35         } catch (BrokenBarrierException e) {
    36             // TODO Auto-generated catch block
    37             e.printStackTrace();
    38         }
    39         
    40     }
    41 }
    42 class mainTask implements Runnable{
    43 
    44     @Override
    45     public void run() {
    46         System.out.println("总任务执行完毕");
    47     }
    48     
    49 }

      执行结果:

     1 pool-1-thread-2正在执行
     2 pool-1-thread-3正在执行
     3 pool-1-thread-1正在执行
     4 pool-1-thread-4正在执行
     5 pool-1-thread-5正在执行
     6 pool-1-thread-2执行完毕,等待其他结果
     7 pool-1-thread-5执行完毕,等待其他结果
     8 pool-1-thread-1执行完毕,等待其他结果
     9 pool-1-thread-4执行完毕,等待其他结果
    10 pool-1-thread-3执行完毕,等待其他结果
    11 总任务执行完毕
    View Code

      另外,CyclicBarrier是可以重用的,它可以在使用完后继续使用,这就是Cyclic(循环)的意思。

  • 相关阅读:
    电脑快捷键大全
    js实现页面跳转
    List转换为字符串方法
    Bootstrap4显示和隐藏元素
    反向代理和正向代理区别
    springboot系列一:工作环境无法联网下快速搭建boot项目
    英语故事系列:冠状病毒传播或导致2020首季度全球经济出现萎缩
    BBS网站的制作
    Flask-SQLAlchemy数据库操作
    step-by-step install Nginx反向代理服务器(Ubuntu 18.04 LTS)(转)
  • 原文地址:https://www.cnblogs.com/lcngu/p/5215332.html
Copyright © 2020-2023  润新知