`
墙头上一根草
  • 浏览: 155228 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java 同步之CountDownLatch、CyclicBarrier

    博客分类:
  • java
阅读更多

    java api提供了很多线程同步有关的类和接口,所有的源码都在java.util.concurrent这个包中,主要原子的类和线程安全的集合框架,还有就是重要的锁的实现,锁的实现在juc的locks这个包中,本节不讨论锁的实现,主要是说明和使用juc下的CountDownLatch和CyclicBarrier

 

  CountDownLatch  源码解释<!-- Generated by javadoc (build 1.6.0-beta2) on Fri Mar 09 12:52:55 CST 2007 -->

<noscript></noscript>

             一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier

CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。

CountDownLatch 的一个有用特性是,它不要求调用 countDown 方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await

           <!-- Generated by javadoc (build 1.6.0-beta2) on Fri Mar 09 12:52:55 CST 2007 -->

    CyclicBarrier  源码解释

<noscript></noscript>

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

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

 

     从api对这两个类的说明可以看出,这两个类都是同步辅助类,这两个类有些相似之处都提供屏障点,即线程在到达屏障点之前都会等待, CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrie

 

    以下是这两个类的使用例子,即把一个大的work分成若干的小work去执行,然后最后计算总的,本例是计算5亿次的加1操作,分别用CountDownLatch 和 CyclicBarrier 实现,直接贴代码部分

 

     

      /**     
* Test2.java Create on 2014年10月9日    
*     
* Copyright (c) 2014年10月9日 by dzh
*     
* @author <a href="xingyu@gw.com.cn">xingyu</a>    
* @version 0.0.1
*    
*/
package org.dzh.lock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

/**@className:Test2.java

 * @description:分段计算5亿次的+1

 * @date 2014年10月9日 上午10:29:29
 */
public class Test2 {
    private static List<Integer> result = new ArrayList<>();
    
    /**@className:Test2.java
    
     * @description:CountDownLatch 实现计算
    
     * @date 2014年10月9日 上午10:30:08
     */
    public static class CDL implements Runnable{
        private final CountDownLatch startSignal;
        private final CountDownLatch doneSignal;
        
        
        CDL(CountDownLatch startSignal,CountDownLatch doneSignal){
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }
        
        @Override
        public void run() {
            try {
                
                this.startSignal.await();
                doWork();
                this.doneSignal.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        void doWork(){
            System.out.println("当前线程的名字是: "+Thread.currentThread().getName());
        }
    }
    
    public static void mainCDL() throws InterruptedException{
        CountDownLatch startSignal = new CountDownLatch(1);//所有的线程都准备好了再开始工作
        CountDownLatch doneSignal = new CountDownLatch(5);//所有的线程都运算结束在开始工作
        
        for (int i = 0; i < 5; i++) {
            new Thread(new CDL(startSignal, doneSignal),"线程"+i).start();
        }
        dosomethingElse();
        startSignal.countDown();//startSignal计数减一,意味着startSignal.await被激活开始工作
        System.out.println("当前数量为:"+startSignal.getCount());
        dosomethingElse();
        doneSignal.await();//在doneSignal计数变为0之前一直等待
        System.out.println("是否结束!");
    }
    
    public static class CDL2 implements Runnable{
        private final CountDownLatch cdl;
        private int startIndex;
        private int endIndex;
        
        CDL2(CountDownLatch cdl,int startIndex,int endIndex){
            this.cdl = cdl;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
        }
        
        @Override
        public void run() {
            int num = 0;
            for (int i = startIndex; i < endIndex; i++) {
                num +=1;
            }
            result.add(num);
            cdl.countDown();
        }
    }
    
    public static void mainCDL2(){
        long startTime = System.currentTimeMillis();
        CountDownLatch cdl = new CountDownLatch(5);
        try {
            result.clear();
            int index = 100000000;
            
            for (int i = 1; i <=5; i++) {
                int num = index*i;
                new Thread(new CDL2(cdl, num-index, num)).start();;
            }
            cdl.await();
            sum();
            System.out.println("计算耗时为: "+(System.currentTimeMillis()-startTime));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    /**@className:Test2.java
    
     * @description:CyclicBarrier 实现计算
    
     * @date 2014年10月9日 上午10:31:03
     */
    public static class CB{
        
         int N;
         final CyclicBarrier cb;
        
         class Worker implements Runnable{
            int myRows;
            
            Worker(int row){
                this.myRows = row;
            }
            
            @Override
            public void run() {
                System.out.println(myRows+" 当前线程计算结束: "+Thread.currentThread().getName());
                try {
                    cb.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
            
         }
        
         CB(){
             cb = new CyclicBarrier(5, new Runnable() {
                
                @Override
                public void run() {
                    System.out.println("当前线程为: "+Thread.currentThread().getName());
                    System.out.println("计算的总和为: "+1000);
                }
            });
            
             for (int i = 0; i < 5; i++) {
                new Thread(new Worker(i)).start();
            }
            
         }
        
        
    }
    
    public static void main(String[] args) throws InterruptedException{
        //mainCDL();
        
//        for (int i = 0; i < 10; i++) {
//            mainCDL2();
//            new Test().cal();
//        }
        
        new CB();
        
    }
    
    static void dosomethingElse(){
        System.out.println("要做点啥呢!");
    }
    
    static void sum(){
        int sum = 0;
        for (int i = 0; i < result.size(); i++) {
            sum += result.get(i);
        }
        System.out.println("计算总和为:"+sum);
    }
}

 

 

分享到:
评论

相关推荐

    Java中的CountDownLatch与CyclicBarrier:深入理解与应用实践

    在Java的并发编程中,CountDownLatch和CyclicBarrier是两个非常重要的同步工具,它们用于协调多个线程的执行顺序。本文将详细介绍CountDownLatch和CyclicBarrier的工作原理、使用场景以及如何在实际项目中应用它们。...

    CountDownLatch和CyclicBarrier用法实例大全

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...

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

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...

    Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    CountDownLatch是Java并发编程中一个重要的工具类,用于协调多线程间的同步。它由Java并发包`java.util.concurrent`提供,主要用于解决一种场景:在主控线程等待多个子线程完成各自任务后再继续执行的情况。下面我们...

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

    在Java并发编程中,CountDownLatch和CyclicBarrier都是用于协调多线程间同步的重要工具,它们可以帮助开发者在特定条件满足时启动或者结束线程的执行。本文将详细探讨这两个类的内部实现机制以及它们在实际应用场景...

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

    AQS 是 Java 并发库的核心之一,提供了构建锁和其他同步组件的基础框架。它通过维护一个名为 state 的共享变量来实现同步,这个变量用于记录锁的状态。 **核心方法:** - **`getState()`:** 获取 state 的当前值。...

    Java中的CountDownLatch类最全讲义

    目录: 简介 1.1 并发编程与线程同步 1.2 CountDownLatch概述 CountDownLatch的基本用法 2.1 创建CountDownLatch对象 2.2 await()方法 ...CountDownLatch与CyclicBarrier的对比 最佳实践与注意事项

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是三种重要的线程协作工具,它们都基于AbstractQueuedSynchronizer(AQS)框架来实现线程间的同步和协调。AQS是一个内置的锁和同步组件,它为构建高级...

    Java并发实例之CyclicBarrier的使用

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

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

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 Java并发编程是Java语言中的一种高级技术,用于处理多线程编程中的同步问题。Java 1.5中引入了几个高效的辅助类,包括CountDownLatch、...

    java同步(一个网页)

    Java同步是Java编程中一个非常重要的概念,主要涉及到多线程环境下的程序控制。在Java中,当多个线程同时访问共享资源时,如果没有适当的同步机制,可能会导致数据不一致、竞态条件等问题。同步机制确保了在特定时间...

    Java异步调用转同步方法实例详解

    Java中将异步调用转换为同步调用有多种方法,本文将详细介绍五种方法:使用wait和notify方法、使用条件锁、使用Future、使用CountDownLatch、使用CyclicBarrier。 1. 使用wait和notify方法 wait和notify方法是...

    Java中的CyclicBarrier类最全讲义

    虽然`CyclicBarrier`和`CountDownLatch`都是Java并发工具包中用于实现线程间协作的工具,但它们之间存在一些关键的区别: - **用途**:`CyclicBarrier`主要用于需要多个线程同时到达一个点的情况,而`...

    Java中CountDownLatch用法解析

    在Java并发编程中,`CountDownLatch`是一个非常重要的工具类,它位于`java.util.concurrent`包下,用于协调多个线程间的同步。`CountDownLatch`的主要作用是允许一个或多个线程等待其他线程完成操作。在上述例子中,...

    如何使用CountDownLatch同步java多线程

    如何使用CountDownLatch同步java多线程 CountDownLatch 是 Java 并发编程中的一种常用工具,用于控制多个线程的并发执行。它可以实现多个线程之间的同步操作,使得线程之间可以协调工作,避免了线程之间的互相干扰...

    Java并发编程之美_部分71

    本节主要讲解了Java并发包中线程同步器原理剖析,具体来说是 CountDownLatch 和 CyclicBarrier 的使用和原理剖析。 一、CountDownLatch CountDownLatch 是一个同步工具,它可以让一个线程等待其他线程完成某些操作...

    Java多线程编程之CountDownLatch同步工具使用实例

    在Java多线程编程中,CountDownLatch是一种常用的同步工具,用于协调多个线程之间的协作,确保它们按照特定的顺序执行或者等待所有线程完成特定任务后再继续执行。这个类是java.util.concurrent包的一部分,提供了...

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

    CyclicBarrier 是 Java 并发编程中的一个同步辅助工具,它允许一组线程全部等待彼此到达公共屏障点。它的字面意思是可循环使用的屏障,用于让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会...

    Java实现进程同步

    5. **CountDownLatch** 和 **CyclicBarrier**:这两个工具类可以帮助我们实现线程间的同步,例如,CountDownLatch可以让一组线程等待其他线程完成操作,而CyclicBarrier则允许一组线程到达一个屏障(或同步点)后...

    java同步

    - **CyclicBarrier和CountDownLatch**:协调多个线程之间的同步,CyclicBarrier允许一组线程等待彼此到达某个点,而CountDownLatch则允许一次释放所有等待的线程。 6. **并发容器** - `java.util.concurrent`包...

Global site tag (gtag.js) - Google Analytics