文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-09-24 16:02

关注

1.使用awaitTermination

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

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

  1. 定义一个 Runnable 接口的实现类,用来执行 SQL 查询任务,该类需要在构造函数中接收 SQL 语句和存储结果的 List 集合对象。
public class SqlQueryTask implements Runnable {    private final String sql;    private final List> resultList;    public SqlQueryTask(String sql, List> 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 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();            }        }    }}
public static void main(String[] args) throws InterruptedException {    // 创建一个 List 集合存储查询结果    List> 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 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> 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> totalResult = new ArrayList<>();        for (Map 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> resultList;    private CountDownLatch latch;    public SqlQueryTask(String url, String user, String password, String sql, List> 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 result = new HashMap<>();            while (rs.next()) {                ResultSetMetaData metaData = rs.getMetaData();                int count = metaData.getColumnCount();                Map 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://blog.csdn.net/weixin_43394692/article/details/130377918

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯