java多线程开发之CyclicBarrier

  最近研究了一个别人的源码,其中用到多个线程并行操作一个文件,并且在所有线程全部结束后才进行主线程后面的处理。

  其用到java.util.concurrent.CyclicBarrier 这个类。

  CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用,其相当于一个屏障,当一个线程跑到await()方法时,将挂起这个线程,等待直到其他线程同样跑这个await()方法。

        int index = --count;
           if (index == 0) {  // tripped
             //。。
         }
          else {
            // We‘re about to finish waiting even if we had not
            // been interrupted, so this interrupt is deemed to
            // "belong" to subsequent execution.
            Thread.currentThread().interrupt();
            }

其是使用一个计数器,当计数器没有减少到0的时候,则会将当前线程中断。

另外,这个是可以重复等待的,重复调用await()方法,将进行重新等待。

构造方法:

CyclicBarrier(int parties)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每个 barrier 上执行预定义的操作。

CyclicBarrier(int parties, Runnable barrierAction)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行

当构造方法传入一个Runnable时,每次到达公共屏障点的时候都最先执行这个传进去的Runnable,然后再执行处于等待的Runnable

    /**
     * CyclicBarrier类似于CountDownLatch也是个计数器,
     * 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,
     * 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。
     * CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
     * CyclicBarrier初始时还可带一个Runnable的参数,
     * 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
     */
public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        //final  CyclicBarrier cb = new CyclicBarrier(3);//创建CyclicBarrier对象并设置3个公共屏障点
        final  CyclicBarrier cb = new CyclicBarrier(3,new Runnable(){
            @Override
            public void run() {
                System.out.println("********我最先执行***********");
            }
        });
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                    public void run(){
                    try {
                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
                        cb.await();//到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行

                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
                        cb.await();    //这里CyclicBarrier对象又可以重用
                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
                        cb.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            service.execute(runnable);
        }
        service.shutdown();
    }
}

另外,其还有一些其他方法

方法摘要
int await()
          在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
int await(long timeout, TimeUnit unit)
          在所有参与者都已经在此屏障上调用 await 方法之前,将一直等待。
int getNumberWaiting()
          返回当前在屏障处等待的参与者数目。
int getParties()
          返回要求启动此 barrier 的参与者数目。
boolean isBroken()
          查询此屏障是否处于损坏状态。
void reset()
          将屏障重置为其初始状态。

。。

方法摘要
int await()
          在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
int await(long timeout, TimeUnit unit)
          在所有参与者都已经在此屏障上调用 await 方法之前,将一直等待。
int getNumberWaiting()
          返回当前在屏障处等待的参与者数目。
int getParties()
          返回要求启动此 barrier 的参与者数目。
boolean isBroken()
          查询此屏障是否处于损坏状态。
void reset()
          将屏障重置为其初始状态。

 1 package com.thread;
 2 import java.util.concurrent.CyclicBarrier;
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.Semaphore;
 6
 7 public class CyclicBarrierTest {
 8
 9     public static void main(String[] args) {
10         ExecutorService service = Executors.newCachedThreadPool();
11         final  CyclicBarrier cb = new CyclicBarrier(3);//创建CyclicBarrier对象并设置3个公共屏障点
12         for(int i=0;i<3;i++){
13             Runnable runnable = new Runnable(){
14                     public void run(){
15                     try {
16                         Thread.sleep((long)(Math.random()*10000));
17                         System.out.println("线程" + Thread.currentThread().getName() +
18                                 "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
19                         cb.await();//到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行
20
21                         Thread.sleep((long)(Math.random()*10000));
22                         System.out.println("线程" + Thread.currentThread().getName() +
23                                 "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
24                         cb.await();
25                         Thread.sleep((long)(Math.random()*10000));
26                         System.out.println("线程" + Thread.currentThread().getName() +
27                                 "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");
28                         cb.await();
29                     } catch (Exception e) {
30                         e.printStackTrace();
31                     }
32                 }
33             };
34             service.execute(runnable);
35         }
36         service.shutdown();
37     }
38 }

线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有0个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点2,当前已有2个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候

  如果在构造CyclicBarrier对象的时候传了一个Runnable对象进去,则每次到达公共屏障点的时候都最先执行这个传进去的Runnable,然后再执行处于等待的Runnable。如果把上面的例子改成下面这样:

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

则结果如下:

线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候
********我最先执行***********
线程pool-1-thread-1即将到达集合地点2,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有2个已经到达,正在等候
********我最先执行***********
线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候
********我最先执行***********

时间: 2024-11-16 03:52:32

java多线程开发之CyclicBarrier的相关文章

iOS多线程开发之GCD(下篇)

上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题.有兴趣的朋友可以回顾<iOS多线程开发之GCD(上篇)>和<iOS多线程开发之GCD(中篇)>. 言归正传,我们首先来回顾下死锁,所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源(如数据源,内存等,变量不是资源)而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去. 死锁形成的原因: 系统资源不足 进程(线程)推进的顺序不恰当: 资源分配不当 死锁形成的条件:

iOS多线程开发之NSOperation - 快上车,没时间解释了!

一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强,很屌的是加入了操作依赖. 默认情况下,NSOperation单独使用时只能同步执行操作,并没有开辟新线程的能力,只有配合NSOperationQueue才能实现异步执行.讲到这里,我们不难发现GCD和NSOperation实现的方式很像,其实这更像是废话,NSOperation本身就是基于GCD的

java多线程--同步屏障CyclicBarrier的使用

CyclicBarrier的概念理解: CyclicBarrier的字面上的意思是可循环的屏障,是java并发包java.util.concurrent 里的一个同步工具类,在我下载的JDK1.6的中文文档里对他的解释是: 大体意思就是:让一组线程到达一个屏障,一个集合点时,被阻塞,直到所有的线程都到了这个集合点时,屏障才会打开,然后线程才能继续往下执行.举个简单的例子就是:旅游团带着一帮人参观景点,规定在下一个景点A处集合,于是导游就在景点A等着大家,导游就是这个集合点或者说屏障,直到所有的游

iOS多线程开发之GCD 用法入门

我们知道,在iOS中进行多线程编程,主要有三种方式:[NSThread].[NSOperation]和[GCD].其中又以[GCD]为苹果官方最为推荐.本文将利用一个简单的demo,简述GCD的用法入门,以及本人对GCD的一点肤浅理解和学习心得. 先把参考文章列出: http://www.cnblogs.com/kenshincui/p/3983982.html http://www.cnblogs.com/sunfrog/p/3305614.html http://mobile.51cto.c

C++多线程开发之actor model

最近想把写过的一个多线程程序整理一下,这个程序主要特点是有一系列的互相之间有依赖关系的task.于是在网上找相关类库 1,一类是简单的线程池了,这也是原本俺的做法.之前使用的是手工调度,代码实现的很蛋疼.外面的lib有poco https://pocoproject.org/slides/130-Threads.pdf2,Intel TBB, MS PPL (Parallel Patterns Library)之类的类库,感觉这里一类本质上和1没有大的分别3,微软的并行库1)MS PPL (Pa

IOS多线程开发之NSThread

概要 使用NSThread的例子,线程创建.启动.线程同步.锁.线程的交互,需要注意的时线程的交互,因为IOS规定只有主线程能够修改UI,所以如果子线程要修改UI的话,需要与主线程交互,即调用方法- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;实现 示例代码 // // ViewController.m // NSThreadDemo // // Crea

Java Web开发之Servlet、JSP基础

有好多年不搞Java Web开发了,这几天正好国庆放假,放松之余也有兴趣回头看看Java Web开发技术的基础. 我们都知道,Servlet是Java Web开发的重要基础,但是由于Servlet开发相对繁琐,代码量庞大而且不易维护,美工无法参与界面设计开发等不足,于是就诞生了jsp.jsp是对servlet开发模型的重要升级.有了jsp,Java Web开发技术才真正被广泛使用. 一.Servlet 在Java Web开发当中,新建一个类继承(派生)自HttpServlet类即可创建一个Ser

iOS 多线程开发之OperationQueue(二)NSOperation VS GCD

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:最近有点忙,所以这个月更新的博客数量有些下降,估计这个月和下个月博客更新的数量都在10篇左右.回到正题,本文会比较下GCD和NSOperation两种多线程的实现方式.然后讲解下如何选择,以及简单的示例. 选择GCD or NSOperationQueue

JAVA微信开发之weixin4j入门视频

weixin4j入门公开课视频 第一课<weixin4j入门视频-新手接入> 视频下载地址: http://pan.baidu.com/s/1o63MdPw 第二课<weixin4j入门视频-接收消息> 视频下载地址: http://pan.baidu.com/s/1i3qzbgT 第三课<weixin4j入门视频-回复消息> 视频下载地址: http://pan.baidu.com/s/1i3qzbgT 视频中的项目源码,请到官方QQ群众获取! 2015年5月26日-