在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景,遇到这样的场景应该如何解决?
如果是一个线程等待一个线程,则可以通过await()和notify()来实现;
如果是一个线程等待多个线程,则就可以使用CountDownLatch和CyclicBarrier来实现比较好的控制。
下面来详细描述下CountDownLatch的应用场景:
例如:百米赛跑:8名运动员同时起跑,由于速度的快慢,肯定有会出现先到终点和晚到终点的情况,而终点有个统计成绩的仪器,当所有选手到达终点时,它会统计所有人的成绩并进行排序,然后把结果发送到汇报成绩的系统。
其实这就是一个CountDownLatch的应用场景:一个线程或多个线程等待其他线程运行达到某一目标后进行自己的下一步工作,而被等待的“其他线程”达到这个目标后继续自己下面的任务。
这个场景中:
1. 被等待的“其他线程”------>8名运动员
2. 等待“其他线程”的这个线程------>终点统计成绩的仪器
那么,如何来通过CountDownLatch来实现上述场景的线程控制和调度呢?
jdk中CountDownLatch类有一个常用的构造方法:CountDownLatch(int count);
两个常用的方法:await()和countdown()
其中count是一个计数器中的初始化数字,比如初始化的数字是2,当一个线程里调用了countdown(),则这个计数器就减一,当线程调用了await(),则这个线程就等待这个计数器变为0,当这个计数器变为0时,这个线程继续自己下面的工作。下面是上述CountDownLatch场景的实现:
Work类(运动员):
import java.util.concurrent.CountDownLatch;
public class Work implements Runnable {
private int id;
private CountDownLatch beginSignal;
private CountDownLatch endSignal;
public Work(int id, CountDownLatch begin, CountDownLatch end) {
this.id = id;
this.beginSignal = begin;
this.endSignal = end;
}
@Override
public void run() {
try {
beginSignal.await();
System.out.println("起跑...");
System.out.println("work" + id + "到达终点");
endSignal.countDown();
System.out.println("work" + id + "继续干其他事情");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Main类(终点统计仪器):
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
CountDownLatch begSignal = new CountDownLatch(1);
CountDownLatch endSignal = new CountDownLatch(8);
for (int i = 0; i < 8; i++) {
new Thread(new Work(i, begSignal, endSignal)).start();
}
try {
begSignal.countDown(); //统一起跑
endSignal.await(); //等待运动员到达终点
System.out.println("结果发送到汇报成绩的系统");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
下面详细描述下CyclicBarrier的应用场景:
有四个游戏玩家玩游戏,游戏有三个关卡,每个关卡必须要所有玩家都到达后才能允许通关。
其实这个场景里的玩家中如果有玩家A先到了关卡1,他必须等待其他所有玩家都到达关卡1时才能通过,也就是说线程之间需要互相等待,这和CountDownLatch的应用场景有区别,CountDownLatch里的线程是到了运行的目标后继续干自己的其他事情,而这里的线程需要等待其他线程后才能继续完成下面的工作。
jdk中CyclicBarrier类有两个常用的构造方法:
1. CyclicBarrier(int parties)
这里的parties也是一个计数器,例如,初始化时parties里的计数是3,于是拥有该CyclicBarrier对象的线程当parties的计数为3时就唤醒,注:这里parties里的计数在运行时当调用CyclicBarrier:await()时,计数就加1,一直加到初始的值
2. CyclicBarrier(int parties, Runnable barrierAction)
这里的parties与上一个构造方法的解释是一样的,这里需要解释的是第二个入参(Runnable barrierAction),这个参数是一个实现Runnable接口的类的对象,也就是说当parties加到初始值时就出发barrierAction的内容。
下面来实现上述的应用场景:
Player类(玩家类)
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Player implements Runnable {
private CyclicBarrier cyclicBarrier;
private int id;
public Player(int id, CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
this.id = id;
}
@Override
public void run() {
try {
System.out.println("玩家" + id + "正在玩第一关...");
cyclicBarrier.await();
System.out.println("玩家" + id + "进入第二关...");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
GameBarrier类(关卡类,这里控制玩家必须全部到达第一关结束的关口才能进入第二关)
import java.util.concurrent.CyclicBarrier;
public class GameBarrier {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, new Runnable() {
@Override
public void run() {
System.out.println("所有玩家进入第二关!");
}
});
for (int i = 0; i < 4; i++) {
new Thread(new Player(i, cyclicBarrier)).start();
}
}
}
相关推荐
java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...
在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...
CountDownLatch和CyclicBarrier是Java并发编程中两个非常有用的同步工具,它们在不同的场景下有着各自的优势。CountDownLatch适用于需要等待一组操作完成的场景,而CyclicBarrier适用于需要多个线程协同工作,直到...
在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...
在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是三种重要的线程协作工具,它们都基于AbstractQueuedSynchronizer(AQS)框架来实现线程间的同步和协调。AQS是一个内置的锁和同步组件,它为构建高级...
Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 ...CountDownLatch、CyclicBarrier和Semaphore都是Java并发编程中非常重要的辅助类,它们可以帮助开发者更好地进行并发编程。
在Java并发编程中,多线程是核心概念之一。多线程允许程序同时执行多个任务,从而充分利用系统资源,提高程序性能。然而,多线程编程也带来了同步和竞态条件等问题,这需要开发者具备良好的线程管理和同步机制的知识...
描述中反复提到“java并发编程艺术”,这暗示书中将详细介绍如何优雅地设计和管理线程,避免常见的并发问题,如死锁、竞态条件和活锁。 在Java中,同步是控制多个线程访问共享资源的方式,主要通过`synchronized`...
通过上述内容的学习,开发者不仅能掌握Java并发编程的基本原理和技术要点,还能学会如何将这些理论应用于实际工作中,解决复杂的多线程问题。无论是对于初学者还是有一定经验的开发者来说,《Java并发编程实战》都是...
Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...
总的来说,《Java并发编程从入门到精通》不仅覆盖了Java并发编程的全面知识,还提供了丰富的实践案例和源码,是Java开发者提升并发编程能力的理想教材。通过深入学习这本书,你将能够掌握并发编程的核心技巧,为成为...
本资料“Java并发编程设计原则和模式”深入探讨了如何在Java环境中有效地进行并发处理,以充分利用系统资源并避免潜在的并发问题。 一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些...
Java并发编程实践是Java...通过这些笔记,我们可以了解到Java并发编程中的关键概念和实践,对于理解和编写高效的并发代码具有极大的帮助。在实际开发中,需要根据具体需求灵活应用这些知识,以保证程序的稳定性和性能。
通过深入学习《JAVA并发编程艺术》,开发者能更好地理解并发编程的原理,熟练运用Java提供的并发工具和API,解决实际开发中的多线程问题,提高软件的性能和稳定性。这是一本值得每一位Java开发者研读的书。
"Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效地实现并发。 并发是指在单个执行单元(如CPU)中同时执行两个或更多任务的能力。在Java中,这主要通过线程来实现,...
Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。阿里大牛梁飞编写的《Java并发编程常识》PPT,深入浅出地讲解了这个主题,对开发者来...
Java并发编程的核心在于理解和使用Java的并发API,包括线程、锁、同步机制以及并发集合等。首先,书中会介绍Java中的线程基础知识,包括如何创建和管理线程,线程的状态以及线程间通信的方法,如wait()、notify()和...