java多线程开发之CyclicBarrier,CountDownLatch

摘要:
CyclicBarrier是一个同步帮助器类,它允许一组线程彼此等待,直到它们到达一个公共的障碍点。CyclicBarrier*最初也可以使用Runnable参数。*此Runnable任务在CyclicBarrier数达到之后,在唤醒所有其他线程之前执行。既然我们提到了CyclicBarrier,我们就不得不提到另一个具有类似功能的工具类:CountDownLatchCyclicBarrar是一个栅栏,它拦截进入await()方法的线程,直到所有线程到达栅栏。

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

  其用到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();
    }
}

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

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

。。

 既然提到了CyclicBarrier,就不得不提到另一个相似功能的工具类:CountDownLatch

CyclicBarrier是一个栅栏,其是将走到await()方法的线程进行拦截,直到等待全部的线程走到这个栅栏。

CountDownLatch是一个计数器,其是线程走到await()方法时,进行等待计数,将在计数到达指定值时才继续往下走。

public class CountDownLatchTest {

    static CountDownLatch c = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(1);
                //进行计数,计数-1
                c.countDown();
                System.out.println(2);
                //进行计数,计数-1
                c.countDown();
            }
        }).start();
        //主线程等待计数
        c.await();
        System.out.println("3");
    }

}             

CountDownLatch当计数到0时,计数无法被重置;CyclicBarrier计数达到指定值时,计数置为0重新开始。
CountDownLatch每次调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响;

CyclicBarrier只有一个await()方法,调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞。

主要方法

 public CountDownLatch(int count);

 public void countDown();

 public void await() throws InterruptedException

 
 

免责声明:文章转载自《java多线程开发之CyclicBarrier,CountDownLatch》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇两个list 求交集效率对比Android第三方推送引擎比较下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JAVA多线程提高十三:同步集合类的应用

 1.引言   在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的。在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操作,都添加synchronized来进行同步,此种方式尽管简单,但是其性能是非常地下的,所以现在已经不怎么使用了。人们普遍会使用并发的容器,在JDK1....

Linux 多线程应用中如何编写安全的信号处理函数

http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerworks/cn/linux/l-cn-signalsec/ Linux 多线程应用中编写安全的信号处理函数 在开发多线程应用时,开发人员一般都会考虑线程安全,会...

C# 创建线程的多种方式之Thread类基础知识

1. Thread类创建线程 该类的构造函数可以接受ThreadStart委托参数(定义了无参,返回void的函数),以及ParameterizedThreadStart委托参数(定义了Object参数,返回void的函数)。 static void Main(string[] args) {...

进程的Binder线程池工作过程

copy from : http://gityuan.com/2016/10/29/binder-thread-pool/ 基于Android 6.0源码剖析,分析Binder线程池以及binder线程启动过程。 frameworks/base/cmds/app_process/app_main.cpp frameworks/native/libs/bin...

java多线程读取、操作List集合

import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.ArrayUtils;   public class Test_4 {     /**      * 多线程处理list      *       * @param ...

CL.exe

CL.exe  CL.exe 是控制 Microsoft C 和 C++ 编译器与链接器的 32 位工具。编译器产生通用对象文件格式 (COFF) 对象 (.obj) 文件。链接器产生可运行文件 (.exe) 或动态链接库文件 (DLL)。 注意,全部编译器选项都区分大写和小写。 若要编译但不链接,请使用 /c。 使用 NMAKE...