`

CyclicBarrier的用法

    博客分类:
  • Java
 
阅读更多
本例介绍第三个同步装置:CyclicBarrier,它维护一个计数器,与CountDownLatch不同的是,等待这个CyclicBarrier的线程必须等到计数器到达某个值时,才可以继续。CyclicBarrier就像它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍。本例实现一个数组相邻元素的加法,一个线程给数组的第一个元素赋值,然后等待其他线程给数组第二个元素赋值,然后将第一个元素和第二个元素相加。

       构造CyclicBarrier对象时,需要指定计数器的目标值,计数器的初始值为0.还可以在构造方法中带一个Runnable参数,表示当计数器到达目标值时,在等待CyclicBarrier的线程被唤醒之前,指定该Runnable任务。
       CyclicBarrier的await方法使当前线程进入等待状态,计数器加1,当计数器到达目标值时,当前线程被唤醒。

 

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

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


构造方法摘要

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




方法摘要

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



package com.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final  CyclicBarrier cb = new CyclicBarrier(3);//创建CyclicBarrier对象并设置3个公共屏障点
        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();   
                        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();
    }
}



线程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。如果把上面的例子改成下面这样:

package com.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

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



线程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个已经到达,正在等候
********我最先执行***********
分享到:
评论

相关推荐

    CountDownLatch和CyclicBarrier用法实例大全

    - 使用CyclicBarrier实现多线程分治策略,每个子任务完成后来一次全局计算的例子。 - 线程间的异常处理,包括中断和超时的处理。 - 结合Future和ExecutorService,进一步提高并发性能和灵活性。 - 在大型项目中的...

    CyclicBarrier用法.docx

    1. **重复使用性**:与CountDownLatch不同,CyclicBarrier可以在所有线程都达到屏障点后重置,允许再次使用。这意味着一旦所有线程都完成各自的任务并调用await()方法,屏障将被重置,计数器恢复到初始值,可以进行...

    java多线程之CyclicBarrier的使用方法

    Java多线程之CyclicBarrier的使用方法 Java多线程之CyclicBarrier的使用方法是Java多线程编程中的一种同步机制,用于实现多个线程之间的同步协作。CyclicBarrier是Java 5中引入的一种同步机制,用于让多个线程等待...

    Java中CyclicBarrier的用法分析

    `CyclicBarrier`的名字来源于它的可重用性,一旦一组线程通过了屏障,它可以重置并再次使用,而不是像`CountDownLatch`那样只能使用一次。 在上述的测试代码中,我们创建了一个`CyclicBarrier`实例,设置了线程数为...

    Java并发实例之CyclicBarrier的使用

    Java并发实例之CyclicBarrier的使用 CyclicBarrier是Java中的一种多线程并发控制实用工具,和CountDownLatch非常类似,它也可以实现线程间的计数等待,但是它的功能比CountDownLatch更加复杂且强大。CyclicBarrier...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...

    Java中的CyclicBarrier类最全讲义

    1. **避免死锁**:在使用`CyclicBarrier`时,确保所有线程都能够正确地调用`await()`方法。如果某个线程未能正确调用`await()`,则可能导致死锁情况。 2. **异常处理**:在调用`await()`方法时,可能会抛出`...

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    在游戏场景中,如果四个玩家需要同时开始游戏,就可以使用CyclicBarrier。`CyclicBarrier(int parties, Runnable barrierAction)`构造函数接受两个参数,`parties`表示需要等待的线程数,`barrierAction`是所有线程...

    JAVA CyclicBarrier类详解.docx

    下面是一个使用CyclicBarrier的典型例子,展示了一个并行分解问题的解决过程: ```java class Solver { final int N; final float[][] data; final CyclicBarrier barrier; class Worker implements Runnable...

    28 人齐了,一起行动—CyclicBarrier详解.pdf

    这个例子展示了 CyclicBarrier 的基本用法: 1. 创建 CyclicBarrier 对象,传入两个参数:第一个参数是计数器的初始值,代表需要等待的线程数量;第二个参数是一个 Runnable,当所有线程到达屏障点并且计数器归零时...

    Java并发编程(CyclicBarrier)实例详解

    CyclicBarrier的使用方法是通过构造方法CyclicBarrier(int parties)来创建,parties表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。CyclicBarrier类还有一...

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

    二、CyclicBarrier用法 CyclicBarrier类也位于java.util.concurrent包下,用于实现多个线程互相等待的功能。CyclicBarrier类提供了以下构造器: public CyclicBarrier(int parties);//参数parties表示等待的线程...

    CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

    - 使用 CyclicBarrier 初始化 N 个线程,这些线程需要共同完成一个任务,只有当所有线程都准备好了之后,它们才能一起开始执行。 **实践案例:** 假设我们有一个复杂的任务,需要分阶段完成,而且每个阶段都需要...

    java线程并发cyclicbarrier类使用示例

    在破裂状态下,`CyclicBarrier`无法恢复,除非调用`reset()`方法。 6. **返回值**:`await()`方法实际上会返回一个整数,表示当前屏障的等待阶段。这在调试和监控中可能有用。 在给出的代码示例中,`...

    java并发编程专题(九)----(JUC)浅析CyclicBarrier

    CyclicBarrier 的使用场景有很多,例如,在一个游戏中,所有玩家都需要等待其他玩家到达某个点时,可以使用 CyclicBarrier 来实现。又例如,在一个科学计算中,多个线程需要等待其他线程完成计算时,也可以使用 ...

    详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    它的核心概念是“代”,每个使用CyclicBarrier的事件都对应一个代,当所有参与线程到达barrier点时,这一代结束,然后可以开始下一轮。CyclicBarrier的`lock`字段用于保护屏障的入口,`trip`条件变量用于线程在...

Global site tag (gtag.js) - Google Analytics