`

CountDownLatch用例及源码解析

    博客分类:
  • JDK
阅读更多
CountDownLatch


官法解释:一个对同步有帮助的类,它允许一个或多个线程等待只到这组操作在其他线程全部完成.
官司用法:初始是由一个给定的count,await方法可以阻塞只到当前count到达0.这是一个自减机制,比如你初始化 count为5,每调用一次countDown,就减1,只到为0,才释放所有线程,但是这种门插锁机制只有一次有效性,如果你想样多次使用,reset,那么推荐使用CyclicBarrier.
官法用例:
两个countdown latches:
1 阻止所有工人行动,只到司机到来才可以行动.
2 阻止司机行动,只到所有工人的工作都已经完成

package org.countdown;

import java.util.concurrent.CountDownLatch;

public class Driver {

		  public static  void main(String args[]) throws InterruptedException {
			  int N= 10;
		      CountDownLatch startSignal = new CountDownLatch(1);
		      CountDownLatch doneSignal = new CountDownLatch(N);
		      print("开始执行...");

		      for (int i = 0; i < N; ++i){ // create and start threads
		    	  print("工人"+i+"到了..");
		        new Thread(new Worker(startSignal, doneSignal,"工人"+i)).start();
		      }

		      print("司机到了");            // don't let run yet
		      startSignal.countDown();      // let all threads proceed
		      print("司机完成任务,等待工人完成中...");
		      doneSignal.await();           // wait for all to finish
		      print("工人全部完成任务,司机截他们回家");
		    }

		private static void print(String message) {
			// TODO Auto-generated method stub
			System.out.println(message);
		}
}


package org.countdown;

import java.util.concurrent.CountDownLatch;

public class Worker implements Runnable {

	private String worker;
	private final CountDownLatch startSignal;
	private final CountDownLatch doneSignal;

	Worker(CountDownLatch startSignal, CountDownLatch doneSignal,String worker) {
		this.startSignal = startSignal;
		this.doneSignal = doneSignal;
		this.worker = worker;
	}

	public void run() {
		try {

			startSignal.await();
			doWork();
			doneSignal.countDown();
			System.out.println(doneSignal.toString());//必须在这里执行,因为在countDown()以上执行是无序的. 只有数了之后才知道还有几个.
		} catch (InterruptedException ex) {
		} // return;
	}

	void doWork() {
		System.out.println(worker+":劳动完成");
	}
}


输出如下:
开始执行...
工人0到了..
工人1到了..
工人2到了..
工人3到了..
工人4到了..
工人5到了..
工人6到了..
工人7到了..
工人8到了..
工人9到了..
司机到了
司机完成任务,等待工人完成中...
工人0:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 9]
工人1:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 8]
工人8:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 7]
工人2:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 6]
工人7:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 5]
工人9:劳动完成
工人5:劳动完成
工人6:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 2]
工人4:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 1]
java.util.concurrent.CountDownLatch@1270b73[Count = 2]
工人3:劳动完成
java.util.concurrent.CountDownLatch@1270b73[Count = 4]
java.util.concurrent.CountDownLatch@1270b73[Count = 0]
工人全部完成任务,司机截他们回家


另一个典型的应用,一个countdown latch:
 在所有工作都完成任务时,和我汇报.
具体见实例2.
其实实例2的功能在实例1已经有了,只是把线程放在Executor上了.
package org.countdown;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Driver2 {

	  public static void main(String args[]) throws InterruptedException {
		  	 int N=10;
		     CountDownLatch doneSignal = new CountDownLatch(N);
		     ExecutorService e = Executors.newFixedThreadPool(N);
		     print("开始执行...");
		     for (int i = 0; i < N; ++i){ // create and start threads
		    	 print("工人"+i+"到了..");
		       e.execute(new WorkerRunnable(doneSignal, i));
		     }
		     System.out.println("所有人都完成了没--没有");
		     //因为处于多线程环境,这些逻辑代码的执行时候没办法计算,随时可能执行
		     doneSignal.await();           // wait for all to finish
		     System.out.println("所有人都完成了没--是的");
		     //在以上的进行等待后,只有到countDown为0时才会释放,可以保证程序的正常执行顺序.  
                     e.shutdown();
		   }

	private static void print(String message) {
		// TODO Auto-generated method stub
		System.out.println(message);
	}
}


package org.countdown;

import java.util.concurrent.CountDownLatch;

public class WorkerRunnable implements Runnable {

	private final CountDownLatch doneSignal;
	private final int i;

	WorkerRunnable(CountDownLatch doneSignal, int i) {
		this.doneSignal = doneSignal;
		this.i = i;
	}

	public void run() {
		doWork(i);
		doneSignal.countDown();
	}

	void doWork(int i) {
		System.out.println("工人" + i + "完成工作");
	}

}
输出结果如下:
开始执行...
工人0到了..
工人1到了..
工人2到了..
工人0完成工作
工人1完成工作
工人3到了..
工人2完成工作
工人4到了..
工人3完成工作
工人4完成工作
工人5到了..
工人6到了..
工人5完成工作
工人7到了..
工人6完成工作
工人8到了..
工人7完成工作
工人9到了..
工人8完成工作
所有人都完成了没--没有
工人9完成工作
所有人都完成了没--是的




关键代码解析:
1.  初始化
public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
}
Sync(int count) {
            setState(count);
}
[AbstractQueuedSynchronizer]
protected final void setState(int newState) {
        state = newState;
}
private volatile int state;//小技巧,信号量可以用volatile修饰,这也是看源码的好外.


这就是我们调用的初始化方法,其实是设置了一个同步的信号量.
2 等待
public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
} 

这就是调用我们等待的方法,当CountDown不是0的时候,继续等待下一个线程,如果没有线程可以等待了,那么跳出模块.
3 记数
public void countDown() {
        sync.releaseShared(1);
}

每次减1,只到为0.
4 得到记数
public long getCount() {
        return sync.getCount();
}


5 打印,挺方便调试的
   public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }

0
0
分享到:
评论

相关推荐

    CountDownLatch源码解析之await()

    CountDownLatch源码解析之await() CountDownLatch是Java并发编程中常用的同步工具,通过await()方法可以让当前线程处于阻塞状态,直到锁存器计数为零(或者线程中断)。下面我们将详细解析CountDownLatch源码之...

    CountDownLatch源码解析之countDown()

    CountDownLatch源码解析之countDown()方法详解 CountDownLatch是Java并发编程中的一种同步工具,用于控制线程的执行顺序。其中,countDown()方法是CountDownLatch的核心方法之一,负责减少计数器的值,并在计数器值...

    多线程countDownLatch方法介绍

    **三、源码解析** 1. `countDown()`方法: ```java public void countDown() { sync.countDown(); } protected final void countDown() { doAcquireSharedInterruptibly(1); } ``` `countDown()`调用`sync....

    CountDownLatch实际应用

    `CountDownLatch`是Java并发库`java.util.concurrent`中的一个工具类,用于协调多个线程间的同步。在上述的实际应用中,`CountDownLatch`被用来控制多线程同时执行并最终将结果汇总到一个集合中。以下是关于`...

    《Java并发编程高阶技术-高性能并发框架源码解析与实战》学习.zip

    《Java并发编程高阶技术-高性能并发框架源码解析与实战》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握高性能并发框架的核心原理,并通过源码解析与实战演练提升技术水平。在Java的世界里,并发编程是提升...

    利用 CountDownLatch 类实现线程同步

    Java 提供了多种工具来实现这样的同步机制,其中之一便是 `CountDownLatch` 类。`CountDownLatch` 是一个计数器,可以用于协调多个线程间的活动,等待所有线程完成各自的任务后,主线程或其他线程才能继续执行。 ...

    CountDownLatch和CyclicBarrier用法实例大全

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

    Java工程师成长之路,包含JDK源码解析、Java并发编程、JVM实例解析、SpringCloud以及各类中间件代码实例与教程

    源码解析可以帮助我们理解Java的核心机制,如垃圾回收、类加载、线程管理等,这对于优化代码性能、排查问题至关重要。深入学习JDK源码可以提升对语言特性的理解和应用,比如深入探讨Collections框架的实现,理解...

    CountDownLatch学习用法

    CountDownLatch是Java并发编程中一个重要的工具类,它属于java.util.concurrent包下的一个同步辅助类。这个类的设计目的是允许一个线程等待其他多个线程完成操作,然后再继续执行。CountDownLatch通常用于多线程协作...

    countdownlatch-example-sourcecode.zip

    《CountDownLatch实战解析与源码探索》 CountDownLatch是Java并发编程中一个非常重要的同步工具类,它在多线程协作场景中起到了关键的作用。在`countdownlatch-example-sourcecode.zip`这个压缩包中,我们可以看到...

    CountDownLatch练习

    CountDownLatch是Java并发编程中一个重要的同步工具类,它允许一个或多个线程等待其他线程完成操作。这个工具在多线程环境下的并行处理和协调中扮演着关键角色。 **CountDownLatch是什么?** CountDownLatch是一个...

    Java中CountDownLatch用法解析

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

    基于JDK源码解析Java领域中的并发锁之设计与实现.pdf

    本文将基于JDK源码解析Java领域中的并发锁,探讨AQS基础同步器、LockSupport、Condition接口、Lock接口、ReadWriteLock接口以及自定义API操作的设计与实现。 一、AQS(AbstractQueuedSynchronizer)基础同步器的...

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

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

    CountDownLatch Demo

    - **测试用例**:在单元测试中,有时需要等待所有异步操作完成后再进行断言。 - **并发任务分阶段执行**:一个大型任务可以被分解成多个子任务,使用 CountDownLatch 让所有子任务完成后,再执行下一步操作。 5. ...

    wardseptember#notes#CountDownLatch源码分析1

    简介countDownLatch这个类使一个主线程等待其他线程执行完毕后再执行。它是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,

    mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁)

    本文将详细介绍如何利用MyBatis结合多线程和CountDownLatch闭锁来实现数据的批量插入。 首先,我们来看`mybatis批处理`。MyBatis的批处理功能允许我们在一次数据库连接中执行多条SQL语句,从而减少了数据库连接的...

    JDK1.8:JDK1.8源码解析-源码解析

    在深入探讨JDK1.8源码解析之前,先理解一下JDK的含义:Java Development Kit,即Java开发工具包,是Java编程语言的核心组成部分,提供了编写、编译和运行Java应用程序所需的所有工具。JDK1.8是Oracle公司发布的Java ...

    CountDownLatch的使用

    递减锁存器CountDownLatch的使用以及注意事项!

    基于JDK源码解析Java领域中的并发锁,我们需要特别关注哪些内容?

    基于JDK源码解析Java并发锁,我们需要关注以下几个关键知识点: 1. **AQS(AbstractQueuedSynchronizer)基础同步器**: AQS是一个用于构建锁和同步器的框架,它维护了一个FIFO的等待队列,提供了两种模式:独占和...

Global site tag (gtag.js) - Google Analytics