java使用CountDownLatch等待多线程全部执行完成

Sure!下面是我为您详细讲解如何在Java中使用CountDownLatch等待多线程全部执行完成的完整攻略。

什么是CountDownLatch

CountDownLatch是Java中的一个同步工具类,它允许一个或多个线程等待直到在其他线程完成的一组操作执行完毕。它主要是用于多线程协同,一个线程需要等待多个其它线程完成某个操作之后才能继续执行。

CountDownLatch的使用

使用CountDownLatch非常简单,主要分为两步:

1.在主线程中,初始化CountDownLatch,并设置需要等待的线程数。

2.在需要等待的线程中,在任务结束时调用CountDownLatch的countDown()方法,代表完成了一个操作。当计数器递减为0时,主线程才会继续执行。

下面是一个基本的CountDownLatch的示例代码:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        // 设置需要等待的线程数
        CountDownLatch countDownLatch = new CountDownLatch(2);

        Thread t1 = new Thread(() -> {
            // 模拟线程1需要执行的操作
            System.out.println("Thread 1 executed.");
            // 操作完成后调用countDown()方法
            countDownLatch.countDown();
        });

        Thread t2 = new Thread(() -> {
            // 模拟线程2需要执行的操作
            System.out.println("Thread 2 executed.");
            // 操作完成后调用countDown()方法
            countDownLatch.countDown();
        });

        t1.start();
        t2.start();

        // 等待两个线程执行完毕
        countDownLatch.await();

        // 所有线程执行完成后,主线程继续执行
        System.out.println("All threads executed.");
    }
}

在上面的代码中,我们初始化了一个CountDownLatch,需要等待两个线程执行完毕,然后启动了两个线程t1和t2,在线程的操作完成后调用了countDown()方法递减计数器。最后,主线程调用了await()方法,等待两个线程执行完毕。在所有线程执行完毕后,主线程才会继续执行,输出"All threads executed."。

示例说明

  • 示例一

现在我们有一个任务需要循环处理一万条数据,每条数据处理时间大约需要1秒。由于数据量比较大,我们可以使用多线程来提高处理速度。我们可以分配10个线程,每个线程处理1000条数据,并使用CountDownLatch来等待所有线程完成任务后再进行计算。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {

    private static final int THREAD_NUMS = 10;
    private static final int DATA_NUMS = 10000;

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMS);

        // 初始化数据
        int[] data = new int[DATA_NUMS];
        for (int i = 0; i < DATA_NUMS; i++) {
            data[i] = i;
        }

        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMS);

        for (int i = 0; i < THREAD_NUMS; i++) {
            final int start = i * (DATA_NUMS / THREAD_NUMS);
            final int end = (i + 1) * (DATA_NUMS / THREAD_NUMS);

            // 加入线程池
            executor.execute(() -> {
                try {
                    // 模拟处理数据
                    Thread.sleep(1000);

                    // 处理数据,这里只输出一下
                    for (int j = start; j < end; j++) {
                        System.out.println("data " + j + " is processed by " + Thread.currentThread().getName());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 操作完成后调用countDown()方法
                    countDownLatch.countDown();
                }
            });
        }

        // 等待所有线程处理完成
        countDownLatch.await();

        // 所有线程已经处理完成,计算结果
        System.out.println("All threads executed. Calculate the sum of data.");
        long sum = 0;
        for (int i = 0; i < DATA_NUMS; i++) {
            sum += data[i];
        }
        System.out.println("The sum of data is " + sum);
        executor.shutdown();
    }
}

在上述代码中,我们初始化了一个CountDownLatch,需要等待10个线程执行完毕。首先我们初始化了一万条数据,然后创建了线程池并加入10个线程。每个线程处理1000条数据,然后调用countDown()方法递减计数器。最后,主线程调用了await()方法,等待10个线程执行完毕。在所有线程执行完毕后,主线程计算了所有数据之和并输出。

  • 示例二

假设你要实现一个游戏服务端的战斗模块,你需要对两个玩家进行匹配并进行战斗。当随机匹配到两个玩家时,需要对两个玩家进行战斗匹配,并等待战斗结束后记录战斗结果。我们可以使用CountDownLatch来控制匹配和战斗的顺序。

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(2);

        Thread matchThread = new Thread(() -> {
            // 随机匹配两个玩家,这里直接模拟随机匹配
            Random random = new Random();
            int playerId1 = random.nextInt(100);
            int playerId2 = random.nextInt(100);
            System.out.println("Match success: playerId1=" + playerId1 + ", playerId2=" + playerId2);
            // 操作完成后调用countDown()方法
            countDownLatch.countDown();
        });

        Thread battleThread = new Thread(() -> {
            try {
                // 等待匹配完成
                countDownLatch.await();

                // 匹配完成后进行战斗,这里直接模拟战斗
                System.out.println("Battle start: Player1 vs Player2");
                Thread.sleep(5000);
                System.out.println("Battle end: Player1 win.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        matchThread.start();
        battleThread.start();

        // 等待战斗结束
        battleThread.join();

        // 输出战斗结果
        System.out.println("Battle completed.");
    }
}

在上述代码中,我们初始化了一个CountDownLatch,需要等待2个线程执行完毕(匹配和战斗)。首先我们创建了随机匹配线程matchThread,并在操作完成后调用了countDown()方法递减计数器。接着我们创建了战斗线程battleThread,需要在匹配完成后进行战斗,所以在战斗线程中先调用await()方法等待匹配完成。在匹配完成后,我们模拟战斗,然后输出战斗结果。最后,主线程等待战斗线程执行完毕并输出战斗完成信息。

总结

至此,我们完成了使用CountDownLatch等待多线程全部执行完成的攻略。通过这篇文章,我们了解了CountDownLatch的基本概念和使用方法,并且也给出了两个示例代码。当你需要等待多个线程执行完毕后再继续执行后续操作时,可以考虑使用CountDownLatch来实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java使用CountDownLatch等待多线程全部执行完成 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • SpringMVC拦截器实现单点登录

    以下是关于“SpringMVC拦截器实现单点登录”的完整攻略,其中包含两个示例。 SpringMVC拦截器实现单点登录 单点登录(Single Sign-On,简称SSO)是一种常见的身份认证机制,它可以让用户在多个应用程序中使用同一组凭证进行登录。在SpringMVC中,我们可以使用拦截器来实现单点登录。 步骤一:创建Maven项目 打开IntelliJ …

    Java 2023年5月17日
    00
  • SpringMVC+Jquery实现Ajax功能

    SpringMVC+Jquery实现Ajax功能的完整攻略 Ajax是一种在Web应用中使用的技术,它可以在不刷新整个页面的情况下,通过异步请求和响应来更新部分页面内容。SpringMVC和Jquery是两个常用的Web开发框架,它们可以很好地结合使用来实现Ajax功能。本文将详细介绍SpringMVC+Jquery实现Ajax功能的完整攻略,并提供两个示例…

    Java 2023年5月17日
    00
  • 通过简单方法实现spring boot web项目

    下面是详细讲解如何通过简单方法实现SpringBoot Web项目的完整攻略。 步骤一:创建SpringBoot项目 首先,在Eclipse或IDEA中创建一个空的Maven项目,并在pom.xml中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId&g…

    Java 2023年5月15日
    00
  • 关于iframe的一点发现与思考

    那么首先让我们来解释一下文章标题中提到的 iframe 是什么东西。 什么是 iframe? iframe 是一种 HTML 元素,用于在当前页面中嵌入其他网页。通过 iframe,我们可以在一张网页中嵌入另一个网页,并且可以在我们网页的其他元素之上或之下显示它。 例如,下面这段 HTML 代码通过 iframe 将百度搜索界面嵌入到当前页面中: <i…

    Java 2023年6月15日
    00
  • 详解HTTP请求与响应基础及实例

    详解HTTP请求与响应基础及实例 HTTP是一种用于网络传输的协议,它定义了客户端和服务器之间进行通信的规则。在HTTP通信过程中,客户端向服务器发送请求,服务器则对请求进行处理并返回响应,由此构成了HTTP请求和响应的基础。 HTTP请求 HTTP请求由三部分构成:请求行、请求头和请求体。其中,请求行包含请求的方法、URI和HTTP版本号,请求头包含了请求…

    Java 2023年5月20日
    00
  • SpringBoot war包部署到Tomcat服务器

    下面我将向您介绍如何将Spring Boot的war文件部署到Tomcat服务器上。 步骤一:修改pom.xml文件 在pom.xml文件中,我们需要将spring-boot-starter-tomcat依赖改为provided,以避免在打包war包时将Tomcat运行时环境打进war包中。代码示例如下: <!–在<dependencies&g…

    Java 2023年5月19日
    00
  • SpringBoot3整合MyBatis出现异常:Property ‘sqlSessionFactory’or ‘sqlSessionTemplate’ are required

    Spring Boot是目前非常受欢迎的开发框架,而MyBatis是一款优秀的数据库ORM框架,二者结合可以让我们开发高效率、高质量的Web应用。不过在整合Spring Boot和MyBatis的时候,有时候会遇到”Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”异常,那么该…

    Java 2023年5月20日
    00
  • spring boot 2.x静态资源会被拦截器拦截的原因分析及解决

    一、问题描述 在使用Spring Boot 2.x开发项目时,我们可能会遇到一个问题,即静态资源(如CSS、JS、图片等)会被拦截器拦截而无法正常加载导致页面样式、交互等异常。这是因为Spring Boot 2.x采用了不同于之前版本的WebMvcConfigurerAdapter配置方式,在配置拦截器时需要特别注意。 二、原因分析 在Spring Boot…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部