线程中的同步辅助类CountDownLatch

简介:

四个类可协助实现常见的专用同步语句。Semaphore 是一个经典的并发工具。CountDownLatch 是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier 是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger 允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的。

 

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

 

等待其他线程:CountDownLatch(其实就是个倒序计数器)

         当其他线程完成之前,该类线程一直处于等待状态.

 

场景需求:

起点裁判倒计时....之后 运动员起跑,然后终点裁判发布成绩.

要让起点裁判线程优先执行.

老师开始给出了一个线程的join方法可以实现这个需求. t.join(); // 优先执行当前线程

但是join不好,因为如果t对应的线程不执行完,其他的所有线程都不会被执行到.

 

可以使用CountDownLatch.

final CountDownLatch cdl1 = new CountDownLatch(1);

刚开始让4个运动员线程处于等待状态,然后判断,有一个计数器int i = 1,裁判线程获得这个计数器.

裁判执行完对应的代码之后,把i变成0,如果运动员获得i=0,就开始执行.

 

要等到最后一个运动员线程执行完,终点裁判宣布成绩.

定义一个初始值是4的计数器,有个运动员到终点就减去1(cdl1.countDown();// 计数器减1).

 

cdl2.await();// 等待计数器变为0

 

CountDownLatchDemo.java

复制代码
 1 import java.util.Random;
 2 import java.util.concurrent.CountDownLatch;
 3 import java.util.concurrent.TimeUnit;
 4 
 5 public class CountDownLatchDemo {
 6 
 7     public static void main(String[] args) throws InterruptedException {
 8         final CountDownLatch cdl1 = new CountDownLatch(1);
 9         final CountDownLatch cdl2 = new CountDownLatch(4);
10 
11         // t.join(); // 优先执行当前线程
12 
13         for (int i = 0; i < 4; i++) {
14             new Thread(new Runnable() {// 运动员
15 
16                         @Override
17                         public void run() {
18                             try {
19                                 cdl1.await(); // 等待计数器变为0
20 
21                                 System.out.println(Thread.currentThread()
22                                         .getName() + " : 起跑");
23                                 TimeUnit.SECONDS.sleep(new Random().nextInt(3));
24                                 System.out.println(Thread.currentThread()
25                                         .getName() + " : 到达终点!");
26                                 cdl2.countDown();
27                             } catch (InterruptedException e) {
28                                 e.printStackTrace();
29                             }
30                         }
31                     }).start();
32         }
33 
34         Thread t = new Thread(new Runnable() {// 发布命令的裁判
35 
36                     @Override
37                     public void run() {
38                         System.out.println("准备");
39                         for (int i = 3; i >= 1; i--) {
40                             System.out.println(i + "...");
41                             try {
42                                 TimeUnit.SECONDS.sleep(1);
43                             } catch (InterruptedException e) {
44                                 e.printStackTrace();
45                             }
46                         }
47                         System.out.println("跑!");
48                         cdl1.countDown();// 计数器减1
49 
50                     }
51                 });
52         t.start();
53         
54         new Thread(new Runnable() {// 宣布成绩的裁判
55 
56             @Override
57             public void run() {
58                 try {
59                     cdl2.await();// 等待计数器变为0
60                 } catch (InterruptedException e) {
61                     e.printStackTrace();
62                 }
63                 System.out.println("宣布成绩!");
64             }
65         }).start();
66         
67     }
68 }
复制代码

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/6206247.html,如需转载请自行联系原作者

相关文章
|
10天前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
16天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3
|
16天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
28 2
|
16天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2
|
16天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
26 1
|
16天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
27 1
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
38 1
C++ 多线程之初识多线程
|
16天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
13 2
|
16天前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
21 1
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
44 6