Java 9并发编程指南 目录

Java并发API提供CountDownLatch类,允许一个或多个线程等待直到一组操作形成。此类初始化时包含一个整型数字,用来记录线程将要等待的操作数量。当线程想要等待这些操作的执行时,使用await()方法,设置线程进入休眠直到操作完成。当其中一个操作完成时,使用countDown()方法减少CountDownLatch类的内置计数器值。当计数器值降到0时,类唤醒所有在await()方法中休眠的线程。

在本节中,学习使用CountDownLatch类实现视频会议系统。此系统需要等待所有参会者到场方可开始。

准备工作

本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。

实现过程

通过如下步骤完成范例:

  1. 创建名为Videoconference的类,实现Runnable接口。这个类将实现视频会议系统:

    public class Videoconference implements Runnable{
    
  2. 定义名为controller的CountDownLatch对象:

    	private final CountDownLatch controller;
    
  3. 实现类构造函数,初始化CountDownLatch属性。Videoconference类接收参会者数量为参数,等待人员到场:

        public Videoconference(int number) {
            controller = new CountDownLatch(number);
        }	
    
  4. 实现arrive()方法,每当一个参会人员到场时调用此方法。接收参数时名为name的字符串类型:

    	public void arrive(String name) {
    
  5. 首先,包含接收的参数信息输出到控制台中:

    		System.out.printf("%s has arrived.\n", name);
    
  6. 然后,调用CountDownLatch对象的countDown()方法:

    		controller.countDown();
    
  7. 最后,输出未到场参会人员的数量信息到控制台中,使用CountDownLatch对象的getCount()方法:

    		System.out.printf("VideoConference: Wait for %d participants.\n", controller.getCount());
    
  8. 接下来,实现视频会议系统的主方法,Runnable接口中必须有的run()方法:

    	@Override
    	public void run() {
    
  9. 首先,使用getCount()方法输出计划参加视频会议的人数信息到控制台中:

    		System.out.printf("VideoConference : Initialization : %d participants.\n", controller.getCount());
    
  10. 然后,使用await()方法等待所有参会者,因为此方法会抛出InterruptedException异常,需要代码进行处理:

    		try {
    			controller.await();
    
  11. 最后,输出信息表明所有的参会者已到达:

                System.out.printf("VideoConference : All the participants have come.\n");
                System.out.printf("VideoConference : Let's start...\n");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
  12. 然后,创建Participant类实现其Runnable接口,此类代表视频会议中的每个参会者:

    public class Participant implements Runnable{
    
  13. 定义名为conference的私有Videoconference属性:

    	private Videoconference conference;
    
  14. 定义名为name的私有字符串属性:

    	private String name;
    
  15. 实现类构造函数,初始化这两个属性:

    	public Participant(Videoconference conference, String name){
    		this.conference = conference;
    		this.name = name;
    	}
    
  16. 实现参会者的run()方法:

    	@Override
    	public void run() {
    
  17. 首先,是指线程随机休眠一段时间:

    		long duration = (long) (Math.random() * 10);
    		try {
    			TimeUnit.SECONDS.sleep(duration);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    
  18. 然后,使用Videoconference属性的arrive()方法指明此参会者到达:

    		conference.arrive(name);
    
  19. 最后,实现范例的主类,创建一个包含main()方法的Main类:

    public class Main {
    	public static void main(String[] args) {
    
  20. 接下来,创建名为conference的Videoconference属性,等待10位参会者:

    		Videoconference conference = new Videoconference(10);
    
  21. 创建Videoconference属性的线程,开始执行:

    		Thread threadConference = new Thread(conference);
    		threadConference.start();
    
  22. 创建10个Participant对象,用Thread对象分别运行它们,然后启动所有线程:

    		for(int i = 0 ; i < 10 ; i ++) {
    			Participant p = new Participant(conference, "Participant" + i);
    			Thread t = new Thread(p);
    			t.start();
    		}
    

工作原理

CountDownLatch类包括三个基础要素:

  • 初始值:确定CountDownLatch对象等待多少事件
  • await()方法,被等待所有事件结束的线程调用
  • countDown()方法,在事件结束执行的时候,被事件调用

当创建CountDownLatch对象时,它使用构造函数的参数初始化一个内置计数器。每次线程调用countDown()方法,CountDownLatch对象的内置计数器值减1。当计数器值等于0时,CountDownLatch对象唤醒所有等待await()方法的线程。

没有方法能够再次初始化或更改CountDownLatch对象的内置计数器值。一旦计数器被初始化,唯一能够修改其值的方法就是之前讲解的countDown()方法。当值等于0时,await()方法的所有调用立即返回,所有后续的countDown()调用均失效。

但是,与其它同步方法有一些不同,如下所示:

  • CountDownLatch机制不保护共享资源或者临界区。它用来同步需要执行各种任务的一个或多个线程。
  • 它只确认一点,如前所述,一旦CountDownLatch的计数器值为0,所有的方法调用均失效。如果想再次进行相同的同步操作,只能创建一个新的对象。

下图显示本范例在控制台输出的执行信息:

等待多并发事件

可以看到参会者如何到达,并且一旦内置计数器值为0,CountDownLatch对象唤醒Videoconference对象,输出表明视频会议可以开始的信息。

扩展学习

以下是CountDownLatch类中await()方法的另一种形式:

  • await(long time, TimeUnit unit):在这个方法中,线程将持续休眠直到它被中断, 也就是说,或者CountDownLatch的内置计数器值变成0,或者已过指定的时间。TimeUnit是一个枚举类型的类,包含如下常量:DAYS、HOURS、MICROSECONDS、MILLISECONDS、MINUTES、NANOSECONDS、和SECONDS。

相关文章:

  • 2021-09-18
  • 2021-08-19
  • 2021-08-15
  • 2021-12-31
  • 2021-09-12
  • 2021-09-12
  • 2021-10-19
猜你喜欢
  • 2022-02-09
  • 2021-10-05
  • 2021-09-10
  • 2022-12-23
  • 2021-07-31
  • 2021-07-30
  • 2021-10-28
相关资源
相似解决方案