`

java多线程编程——同步器CountDownLatch(三)

阅读更多
CountDownLatch主要起倒计时计数器作用,它主要有两个方法await()和countDown()。一旦某个线程调用await()方法,那么该线程就会阻塞,等待CountDownLatch计数器倒计时归零,需要注意的是尽管线程调用await()方法后会阻塞,但是CountDownLatch允许别的线程调用countDown()方法,将计数器减一。也就是说调用计时器的线程阻塞后,可以利用别的线程控制调用线程何时从新开始运行。
package demo;

import java.util.concurrent.CountDownLatch;

/**
 * 该demo主要想要做的事就是:在主线程中创建N个支线程,让支线程等待主线程将开关计数器startSignal打开。
 * 而当主线程打开startSignal开关后,主线程要等待计数器doneSignal归零,
 * 而doneSignal计数器归零依赖于每个支线程为主线程的计数器减一。
 * 所以当主线程打开开关后,支线程才能运行完毕,而只有支线程全部运行完毕,才能打开主线程的计数器。 这样整个程序才能走完
 * 
 * @author Administrator
 * 
 */
public class LatchDriverDemo {
	public static final int N = 5;

	public static void main(String[] args) throws InterruptedException {
		// 用于向工作线程发送启动信号
		CountDownLatch startSignal = new CountDownLatch(1);
		// 用于等待工作线程的结束信号
		CountDownLatch doneSignal = new CountDownLatch(N);
		// 创建启动线程
		System.out
				.println("开始创建并运行分支线程,且分支线程启动startSignal计数器,等待主线程将startSignal计数器打开");
		for (int i = 0; i < N; i++) {
			new Thread(new LatchWorker(startSignal, doneSignal), "t" + i)
					.start();
		}
		// 得到线程开始工作的时间
		long start = System.nanoTime();
		// 主线程,递减开始计数器,让所有线程开始工作
		System.out.println("主线程" + Thread.currentThread().getName()
				+ "将startSignal计数器打开");
		startSignal.countDown();
		// 主线程阻塞,等待所有线程完成
		System.out.println("主线程" + Thread.currentThread().getName()
				+ "开始倒计时5个数");
		doneSignal.await();
		/*
		 * 为什么说运行到下一句,所有线程就全部运行完毕了呢。 因为主线程要倒计时5个数, 而产生的5个支线程在运行完毕前会将主线程的计数器减一,
		 * 所以如果所有支线程运行完毕了 ,主线程才能继续运行主线程的最后一个打印程序
		 */
		System.out.println("所有线程运行完毕");
	}
}

class LatchWorker implements Runnable {
	// 用于等待启动信号
	private final CountDownLatch startSignal;
	// 用于发送结束信号
	private final CountDownLatch doneSignal;

	LatchWorker(CountDownLatch startSignal, CountDownLatch doneSignal) {
		this.startSignal = startSignal;
		this.doneSignal = doneSignal;
	}

	public void run() {
		try {
			// 一旦调用await()方法,该线程就会开始阻塞。知道计数器startSignal为0
			System.out.println(Thread.currentThread().getName()
					+ " 开始调用await()方法,等待计数器startSignal被主线程打开");
			startSignal.await();
			doWork();
			System.out
					.println(Thread.currentThread().getName() + " 将主线程的计数器减一");
			doneSignal.countDown();// 发送完成信号
		} catch (InterruptedException ex) {
		}
	}

	void doWork() {
		System.out.println(Thread.currentThread().getName()
				+ " 的计数器被打开,分支线程开始运行");
		int sum = 0;
		for (int i = 0; i < 10000; i++) {
			sum += i;
		}
	}
}


程序运行结果:

    开始创建并运行分支线程,且分支线程启动startSignal计数器,等待主线程将startSignal计数器打开
    t0 开始调用await()方法,等待计数器startSignal被主线程打开
    t1 开始调用await()方法,等待计数器startSignal被主线程打开
    t2 开始调用await()方法,等待计数器startSignal被主线程打开
    主线程main将startSignal计数器打开
    t4 开始调用await()方法,等待计数器startSignal被主线程打开
    t3 开始调用await()方法,等待计数器startSignal被主线程打开
    t3 的计数器被打开,分支线程开始运行
    t0 的计数器被打开,分支线程开始运行
    t2 的计数器被打开,分支线程开始运行
    t3 将主线程的计数器减一
    t0 将主线程的计数器减一
    t2 将主线程的计数器减一
    t4 的计数器被打开,分支线程开始运行
    t1 的计数器被打开,分支线程开始运行
    主线程main开始倒计时5个数
    t4 将主线程的计数器减一
    t1 将主线程的计数器减一
    所有线程运行完毕
分享到:
评论
2 楼 gophern 2015-06-12  
漂亮,说明和示例都很精要!
1 楼 hwy1782 2011-10-18  
不错,正要使用

相关推荐

    Java多线程运算集合

    - Java多线程编程涉及多个方面的知识和技术,从基本的线程创建到高级的同步机制,都是开发高效、可靠的多线程应用程序所必需的。 - 正确理解和使用这些技术对于提高程序性能、避免死锁等问题至关重要。

    并发编程——并发工具类.pdf

    并发工具类则是Java中用于支持多线程协作和同步控制的一系列工具,它们可以简化并发控制逻辑,提高开发效率,并且减少因并发编程带来的错误。 #### 标题与描述解析 标题“并发编程——并发工具类.pdf”预示了文档...

    多线程面试题

    多线程面试题往往会围绕线程的概念、特性、线程安全、锁机制以及多线程编程中可能遇到的问题和解决方案进行提问。 线程是操作系统能够进行运算调度的最小单位,它是进程中的一个实体,是被包含在进程之中的。一个...

    java高并发编程推荐超好的一本电子书

    `ThreadLocal`为每个使用该变量的线程提供独立的副本,线程之间不会相互干扰,从而解决了多线程之间的数据共享问题。 #### 3. 避免过度同步 过度同步会导致性能下降,因此在设计时应尽量减少同步操作。例如,可以...

    一个简单的线程同步实例

    线程同步是多线程编程中的重要概念,它主要用于解决多个线程并发访问共享资源时可能出现的竞争条件问题,确保数据的正确性和程序的稳定性。在Java等编程语言中,线程同步可以通过多种方式实现,本实例将探讨其中的几...

    java葵花宝典——各种问题详细解答

    4. **多线程** - **并发编程**:理解线程的基本概念,如何创建和管理线程,以及同步机制(如synchronized、volatile、Lock接口)的使用,是开发高并发应用的基础。 - **线程池**:ExecutorService和...

    Java并发编程实践.rar

    介绍Java并发编程中常用的集合框架,如ConcurrentHashMap、CopyOnWriteArrayList等,它们是如何在多线程环境下保证数据一致性与高效性的。 第五章:线程池 分析ExecutorService和ThreadPoolExecutor,解释如何配置...

    Java实现进程同步

    Java作为一种强大的多线程编程语言,提供了丰富的API来支持进程同步。本篇文章将深入探讨如何使用Java实现“生产者-消费者”问题的进程同步。 生产者-消费者问题是多线程设计模式中的一个经典案例,它模拟了两个...

    Java并发编程实践

    书中会详细介绍各种同步工具类,如`java.util.concurrent`包下的`Semaphore`信号量、`CyclicBarrier`回环屏障、`CountDownLatch`倒计时器以及`ExecutorService`和`Future`等。这些工具提供了更高级别的同步和协作...

    java面试——深圳-中国平安-Java中级.zip

    3. **多线程**: - **线程创建**:使用Thread类和Runnable接口创建线程。 - **同步机制**:synchronized、Lock、volatile关键字的应用及其原理。 - **并发工具类**:如Semaphore、CountDownLatch、CyclicBarrier...

    java面试——杭州-阿里云-Java中级.zip

    3. **多线程**:掌握线程的创建方式(Thread类、Runnable接口)、线程同步机制(synchronized关键字、wait/notify、Lock接口及其实现类)、并发工具类(如CountDownLatch、CyclicBarrier、Semaphore)以及线程池...

    Java并发编程实战(中文版).7z

    这本书全面地介绍了如何在Java平台上高效、安全地编写多线程程序,帮助读者理解并解决并发编程中的各种挑战。 首先,我们需要理解“并发”这个概念。并发是指在一段时间内,多个任务可以同时进行或交替执行。在单...

    java面试——上海-携程-Java高级.zip

    3. **多线程** - 线程的创建方式:Thread类和Runnable接口,以及线程池的使用。 - 线程同步:synchronized关键字、volatile变量、Lock接口(如ReentrantLock)以及Condition。 - 死锁、活锁和饥饿现象的识别与...

    java 模拟快车下载器

    Java模拟快车下载器是一种利用Java编程语言实现的下载工具,它...通过这个项目,开发者不仅可以提升Java技术,还能深入了解网络通信和多线程编程。而"flashget"这个文件可能包含了示例代码或相关资源,供你参考和学习。

    java面试——深圳-蚂蚁金服-Java高级.zip

    在Java高级面试中,尤其是像蚂蚁金服这样的顶级科技公司,面试官通常会考察候选人在核心Java、并发处理、集合框架、多线程、垃圾回收、设计模式、数据库操作、网络编程、性能优化等多个领域的深入理解和应用能力。...

    115个Java面试题和答案——终极(上)_尚硅谷_宋红康.zip ) 您可以上传小于60MB的文件

    - **线程**:Java提供了Thread类和Runnable接口来实现多线程。线程间的同步和通信是面试常见问题,包括synchronized关键字、wait/notify机制、Lock接口等。 - **并发工具类**:如Semaphore(信号量),...

    java面试——深圳-丰巢科技-Java高级.zip

    在Java高级面试中,面试官通常会关注应聘者对核心概念、并发处理、集合框架、设计模式、数据库操作、性能优化、垃圾收集以及框架应用等多个方面的理解和实践能力。以下是根据这些关键点展开的详细知识点: 1. **...

    java经典问题.rar

    2. **多线程**:Java提供了丰富的API来支持多线程编程,包括Thread类、Runnable接口,以及synchronized关键字、wait()、notify()等同步机制。 3. **集合框架**:Java集合框架包括List、Set、Map等接口及其实现类,...

    【Java面试题汇总】——超全,建议多次学习,经常复习,常看常新!.rar

    5. **多线程**:包括线程的基本概念、创建方式(继承Thread类、实现Runnable接口、使用ExecutorService)、线程同步(synchronized、Lock、信号量等)以及并发工具类(CountDownLatch、CyclicBarrier、Semaphore等)...

    RoadMap —— Java后端开发技能路书.zip

    5. **多线程编程**:Java内置了对多线程的支持,包括Thread类、Runnable接口,以及并发工具类如Semaphore、CountDownLatch等。理解线程同步和通信机制,如synchronized关键字、wait/notify、Lock接口,对于编写并发...

Global site tag (gtag.js) - Google Analytics