介绍
CountDownLatch是JDK5引入的一个新的线程辅助类,用于帮助开发人员”比较精确"的控制线程状态。CountDownLatch这个类内置了一个锁计数器,这个计数器由新建这个类的实例时指定,每调用countDown()方法一次,计数器的数字减一,当计数器为零时,所有的等待线程被释放并执行,否则这些线程是处于等待状态。
这个类在两种典型的场合下可以用得到。
第一种场合是若干个线程必须等待一个事件或者一些动作发生后才开始执行。比如,博尔特和其他7位在百米赛场上的选手必须等到发令枪响后才可以起跑,最后一位选手冲过终点时,百米跑比赛结束。这种情况下需要用参数1来初始化。
第二种场合是某件事情或者动作必须等到所有的线程都执行完后才发生执行。比如装配汽车的时候,4个工人装配4个轮子,只有4个轮子都被安装好后,流水线才能让这辆汽车进入下一个装配环节。这种情况下,用参数4来初始化。当然,这种情况,也可以用CyclicBarrier类来控制。
百米飞人大战
首先用代码模拟第一种场合。在Player类中有一个锁,让运动员处于等待状态。只有等一声发令枪响后,运动员才可以起跑。latch.await()方法正是起到了这个效果。Player中run1私有函数让线程休眠10秒钟内的一个随即时间,模拟运动员在跑的过程中,跑完后,运动员抵达终点。
在main函数中,新建一个CountDownLatch,并且设置计算器为1。接着新建一个可以同时运行8个线程的线程池-- 模拟赛道,通过调用ExecuteService.execute()函数,让所有的运动员都进入这个赛道。这个时候,计数器的值为1,所有的线程是处于等待状态。OK,接下来,调用latch.countDown(),让锁计数器为零。ExecutorService中的8个线程同时启动,所有的运动员起跑。 最后,ExecutorService.shutdown()函数会等待线程池中的8个线程全部执行完后,关闭线程池,--- 比赛结束。
class Player implements Runnable {
private String name;
private CountDownLatch latch;
public Player(String name, CountDownLatch latch) {
super();
this.name = name;
this.latch = latch;
}
@Override
public void run() {
try {
latch.await();
run1();
System.out.format("Player %s reaches the endponit.%n", name);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void run1() throws InterruptedException {
Thread.sleep(new Random().nextInt(10000));
}
public static void main(String args[]) {
CountDownLatch latch = new CountDownLatch(1);
ExecutorService executor = Executors.newFixedThreadPool(8);
String players[] = { "Bolt", "Robles", "Liu Xiang", "Johnson", "Louis", "Gatlin", "Green", "Robert" };
for (int i = 0; i < 8; i++)
executor.execute(new Player(players[i], latch));
latch.countDown();
executor.shutdown();
}
}
装配汽车轮子
假设有4个工人在汽车生产流水线上同时装配一辆汽车上的4个轮子,因为每个工人装配轮子的速度会不一样,在汽车进入下一个作业环节前,生产流水线必须知道这辆汽车的4个轮子已经被装配好。首先设置计算器为4, 当一个工人把轮子装好后,按下按钮,让计数器减一,计数器的值变成3,最后,4个工人全部按下按钮后,计数器的值变成零。一旦计数器为零,生产线的控制程序让这辆车,进入下一个装配作业环节。
先看一下Worker类,代表一个可以安装车轮的工人,为了能明确的表示一个车轮,这里车轮被抽象成一个数字,用id代表。Worker.run()方法调用marshalTyre()私有成员函数 ------代表装配轮子,只不过是让该线程休眠了60s内的一个随机时间。实际上,该方法是主要的业务代码,完成了轮子的装配工作。当工人完成自己的工作后,调用latch.countDown()方法,按下计算器按钮,告诉生产线控制中心,表示我已经完成了按照轮子的任务。哈,我可以去喝口水了。
再看一下main函数中的latch.await()这行,表示,流水线一直在等待计数器被清零。当计算器为零后,可以统计这次装配用的整时间啦。
public class Worker implements Runnable {
private int id;
private CountDownLatch latch;
public Worker(int id, CountDownLatch latch) {
this.id = id;
this.latch = latch;
}
@Override
public void run() {
try {
System.out.format("tyre %d is assembling.%n", id);
marshalTyre();
System.out.format("tyre %d is assembled.%n", id);
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void marshalTyre() throws InterruptedException {
Thread.sleep(new Random().nextInt(60000));
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(4);
ExecutorService executor = Executors.newFixedThreadPool(4);
long s = System.currentTimeMillis();
for (int i = 0; i < 4; i++)
executor.execute(new Worker(i, latch));
latch.await();
System.out.format("the 4 tyres were assembled. costs %d ms.%n", System.currentTimeMillis() - s);
executor.shutdown();
}
}
好了,我们对这个例子进行拓展,工人在装配轮胎之前,轮胎必须是已经放到了合适的位置,假如这辆车到达的时候,轮胎还没有准备好,那么必须等到轮胎准备就绪后才可以开始安装工作。换住话说,轮胎没有准备好,工人就一直处于等待“轮胎就绪”这个事件上。当轮胎准备好后,才可以安装。这种情况下,需要用到两把CountDownLatch。具体怎么用,下次再写。
[原创内容,版权所有,如有转载,请注明出处,如有错误之处,请指出,不胜感激]
分享到:
相关推荐
java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
锁机制是Java并发编程中的另一大主题,包括内置锁(互斥锁)和显式锁(如`ReentrantLock`)。内置锁是`synchronized`关键字提供的,而显式锁提供了更细粒度的控制和更丰富的功能。书中可能还会讨论读写锁(`...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
根据提供的信息,“Java 并发编程实战.pdf”这本书聚焦于Java并发编程的实践与应用,旨在帮助读者深入了解并掌握...无论是对于初学者还是有一定经验的开发者来说,《Java并发编程实战》都是一本值得深入学习的好书。
在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...
《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...
《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...
Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...
《Java并发编程从入门到精通》是一本专为Java开发者设计的深度学习并发编程的书籍。作者韩剑锋,凭借其12年的IT行业经验,曾担任多家IT公司的研发总监和技术总监,以其丰富的实战经验和深厚的理论知识,为读者提供了...
在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是三种重要的线程协作工具,它们都基于AbstractQueuedSynchronizer(AQS)框架来实现线程间的同步和协调。AQS是一个内置的锁和同步组件,它为构建高级...
"Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效地实现并发。 并发是指在单个执行单元(如CPU)中同时执行两个或更多任务的能力。在Java中,这主要通过线程来实现,...
### Java并发编程实践 #### 一、并发编程基础 ##### 1.1 并发与并行的区别 在Java并发编程中,首先需要理解“并发”(Concurrency)和“并行”(Parallelism)的区别。“并发”指的是多个任务在同一时间段内交替...
Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...
Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...
本资料“Java并发编程设计原则和模式”深入探讨了如何在Java环境中有效地进行并发处理,以充分利用系统资源并避免潜在的并发问题。 一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些...
### 一、Java并发编程基础 #### 1.1 并发与并行的概念 - **并发**:指多个事件在同一时间段内发生。 - **并行**:指多个事件在同一时刻发生。 在Java并发编程中,通常会涉及多个线程共享资源并同时运行的情况,...
《Java并发编程实战》是Java开发者深入理解和掌握并发编程的一本经典著作。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者在多核时代编写出高效、可伸缩且线程安全的代码。 并发编程是现代...
阿里大牛梁飞编写的《Java并发编程常识》PPT,深入浅出地讲解了这个主题,对开发者来说是一份宝贵的资源。 首先,我们来探讨Java并发编程的基础概念。并发是指多个执行单元(线程或进程)在同一时间间隔内同时进行...