在Java中如何确保在多线程情况下,所有线程都完成再继续执行任务?

这篇具有很好参考价值的文章主要介绍了在Java中如何确保在多线程情况下,所有线程都完成再继续执行任务?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.使用awaitTermination

        awaitTermination是executorService自带的方法,用来确保所有的线程任务都执行完毕。

例如下使用线程池来执行100个不同的 SQL 语句,将查询结果存储在一个 List 集合中,具体实现如下:

  1. 定义一个 Runnable 接口的实现类,用来执行 SQL 查询任务,该类需要在构造函数中接收 SQL 语句和存储结果的 List 集合对象。
public class SqlQueryTask implements Runnable {
    private final String sql;
    private final List<Map<String, Object>> resultList;

    public SqlQueryTask(String sql, List<Map<String, Object>> resultList) {
        this.sql = sql;
        this.resultList = resultList;
    }

    @Override
    public void run() {
        // 执行 SQL 查询,并将结果存储在 resultList 中
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs.next()) {
                Map<String, Object> rowMap = new HashMap<>();
                // 获取查询结果的每一列的名称和值,并将其存储在 Map 中
                ResultSetMetaData metaData = rs.getMetaData();
                int count = metaData.getColumnCount();
                for (int i = 1; i <= count; i++) {
                    String columnName = metaData.getColumnName(i);
                    Object columnValue = rs.getObject(i);
                    rowMap.put(columnName, columnValue);
                }
                // 将该行数据添加到结果 List 集合中
                resultList.add(rowMap);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}
  • 2、在主线程中,创建一个 List 集合对象存储查询结果,再创建一个线程池对象,然后将100个 SQL 查询任务提交给线程池。
public static void main(String[] args) throws InterruptedException {
    // 创建一个 List 集合存储查询结果
    List<Map<String, Object>> resultList = new ArrayList<>();

    // 创建一个线程池对象
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    // 循环提交100个 SQL 查询任务给线程池
    for (int i = 1; i <= 100; i++) {
        String sql = "SELECT * FROM table" + i + ";";
        SqlQueryTask task = new SqlQueryTask(sql, resultList);
        executorService.execute(task);
    }

    // 等待所有任务执行完成
    executorService.shutdown();
    executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

    // 输出查询结果
    for (Map<String, Object> rowMap : resultList) {
        System.out.println(rowMap);
    }
}

 2、使用CountDownLatch 

 

 

        在多线程环境下,需要保证线程安全,避免出现线程竞争和线程之间的互相干扰。针对这种需要保证多线程运行情况下执行 1000 条 SQL 语句的需求,可以使用 CountDownLatch 来实现线程同步和确保所有的 SQL 查询任务都已经执行完成后再执行后面的代码逻辑。

  1. 在主线程中,创建一个 CountDownLatch 对象并设置计数器为 1000,再创建一个 List 集合对象存储查询结果。

  2. 在每个 SQL 查询任务中,执行 SQL 查询,并将查询结果存储在 List 集合中,最后将 CountDownLatch 的计数器减 1。

  3. 在主线程中,调用 CountDownLatch 的 await() 方法在所有 SQL 查询任务执行完成前阻塞线程,直到计数器减为 0 时,所有任务都已经执行完成可以继续往下执行,此时可以对查询结果进行汇总处理。

下面是一个示例代码:

import java.sql.*;
import java.util.*;
import java.util.concurrent.*;

public class SqlQueryDemo {
    private static final int TASK_COUNT = 1000;

    public static void main(String[] args) throws InterruptedException {
        String url = "jdbc:mysql://localhost:3306/test";
        String user = "root";
        String password = "";
        int threads = 10;

        // 创建 CountDownLatch 对象
        CountDownLatch latch = new CountDownLatch(TASK_COUNT);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(threads);

        // 创建 List 存储查询结果
        List<Map<String, Object>> resultList = new ArrayList<>();

        // 提交 SQL 查询任务
        for (int i = 1; i <= TASK_COUNT; i++) {
            String sql = "SELECT * FROM table" + i + ";";
            executorService.execute(new SqlQueryTask(url, user, password, sql, resultList, latch));
        }

        // 等待所有任务执行完成
        latch.await();

        // 关闭线程池
        executorService.shutdown();

        // 合并查询结果
        List<Map<String, Object>> totalResult = new ArrayList<>();
        for (Map<String, Object> result : resultList) {
            totalResult.addAll(result.values());
        }
        // TODO: 执行后面的代码逻辑,使用 totalResult 对查询结果进行汇总处理
    }
}

class SqlQueryTask implements Runnable {
    private String url;
    private String user;
    private String password;
    private String sql;
    private List<Map<String, Object>> resultList;
    private CountDownLatch latch;

    public SqlQueryTask(String url, String user, String password, String sql, List<Map<String, Object>> resultList, CountDownLatch latch) {
        this.url = url;
        this.user = user;
        this.password = password;
        this.sql = sql;
        this.resultList = resultList;
        this.latch = latch;
    }

    @Override
    public void run() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            // 执行 SQL 查询,并将查询结果存储在 List 中
            conn = DriverManager.getConnection(url, user, password);
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            Map<String, Object> result = new HashMap<>();
            while (rs.next()) {
                ResultSetMetaData metaData = rs.getMetaData();
                int count = metaData.getColumnCount();
                Map<String, Object> row = new HashMap<>();
                for (int i = 1; i <= count; i++) {
                    String columnName = metaData.getColumnName(i);
                    Object columnValue = rs.getObject(i);
                    row.put(columnName, columnValue);
                }
                result.put(sql, row);
            }
            resultList.add(result);
            // CountDownLatch 计数器减 1
            latch.countDown();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

        在以上示例代码中,当每个 SQL 查询任务执行完毕后都将 CountDownLatch 计数器减 1,当计数器减为 0 时,主线程的 await() 方法返回,程序继续执行后面的逻辑,汇总所有 SQL 查询结果并进行处理。文章来源地址https://www.toymoban.com/news/detail-511571.html

到了这里,关于在Java中如何确保在多线程情况下,所有线程都完成再继续执行任务?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java: 模块循环不支持注解处理。请确保将循环中的所有模块排除在注解处理之外

    java: 模块循环不支持注解处理。请确保将循环中的所有模块排除在注解处理之外 大概意思是有循环依赖问题 解决方法: 选择模块依赖项 找到需要解决依赖的模块分析依赖,删除不需要的依赖 如果出现其他问题,再根据提示添加依赖即可

    2024年02月16日
    浏览(42)
  • 驱动仅提供32位刷写的情况下如何完成刷写单数字节

    前情提要:需要刷写一整个app程序,分包刷写,每包字节数为单数,要求CRC校验正确。(芯片底层提供32位全字刷写和16位半字刷写,驱动只整合了32位全字刷写函数) 使用32位刷写函数出现的现象:通过keil5观察内存空间发现一包刷写成功一包刷写失败一包刷写成功...一直循

    2024年02月13日
    浏览(41)
  • Socks5代理在多线程爬虫中的应用

    在进行爬虫开发过程中,我们常常需要处理大量的数据,并执行多任务并发操作。然而,频繁的请求可能会引起目标网站的反爬机制,导致IP封禁或限制访问。为了规避这些限制,我们可以借助Socks5代理的强大功能,通过多线程爬虫来实现高效而稳定的数据获取。本文将为您

    2024年02月12日
    浏览(43)
  • HTTP/HTTPS代理IP在多线程爬虫项目中的实践

    在多线程爬虫项目中,HTTP/HTTPS代理IP的实践主要包括以下几个关键步骤: 1. 收集代理IP资源:    - 从免费或付费代理IP提供商、公开代理列表网站(如西刺代理、无忧代理等)抓取代理IP和端口信息。    - 存储这些IP到数据库或者文件中,格式通常为`ip:port`。 2. 构建代理池

    2024年01月22日
    浏览(54)
  • 【经验】Git|如何删除错误的commit?(存在大文件无法push的commit、不需要的commit等情况、清除所有commit的情况)

    如果你在本地多次提交了commit,但是其中有一个commit交错了、或者无法推送, 就像下面这张图这样: 你可以安装以下步骤操作。 通过 git log 想清楚自己需要切换到哪一个commit状态,查看commit id: 将仓库的状态恢复到 能够正常提交的状态/需要删除的状态的上一个commit状态

    2024年02月03日
    浏览(69)
  • 如何在多租户环境中实现高度的隔离与安全

    在当今的互联网时代,多租户系统已经成为企业和组织中不可或缺的技术基础设施。多租户系统可以让多个租户共享同一个系统,从而降低成本,提高资源利用率。然而,在多租户环境中,如何实现高度的隔离与安全成为了一个重要的技术挑战。 在这篇文章中,我们将从以下

    2024年02月22日
    浏览(38)
  • 一劳永逸安装程序无法继续 Microsoft Runtime DLL 安装程序未能完成安装

    在原先安装过一次VM,在学习ROS的时候,尝试将win里的code拖进Ununtu,结果直接给我干蓝屏了,重启几次之后,依然发现如此,一怒之下卸载了VM,打算重新安装,在尝试了一下午的安装之后,由于 安装程序无法继续 Microsoft Runtime DLL 安装程序未能完成安装 一直给我报错,一怒

    2024年02月05日
    浏览(68)
  • (18)线程的实例认识:线程的控制,暂停,继续,停止,线程相互控制,协作

          话不多,但比较中肯,本文参照c# 线程暂停继续的实现方式_哔哩哔哩_bilibili      1、这是一个老的实现方式,基本不推荐, 背后控制的原理需要了解。         界面:三个button一个textbox                           代码:         上面一直在异步线程中无限

    2024年02月10日
    浏览(41)
  • C++中确保线程安全的几种方式

    在 C++ 中,可以使用以下几种方式来确保线程安全: 使用互斥量(mutex)来对共享资源进行保护。互斥量可以用来防止多个线程同时访问共享资源,从而避免数据竞争的问题。 使用读写锁(reader-writer lock)来对共享资源进行保护。读写锁允许多个读线程同时访问共享资源,但

    2023年04月17日
    浏览(44)
  • VMware 无法连接到虚拟机。请确保您有权利运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录或VMX提前退出。

    VMware 无法连接到虚拟机。请确保您有权利运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录或VMX提前退出。 原因:虚拟机VMware已遭到破坏,虚拟机权限认证服务无法启动。 ***解决办法:***进去服务中,把VMware Authorization Service的启动类型改为延迟启动。 1、

    2024年02月05日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包