Java多线程批量处理数据

package com.demo.studydemo.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 批量数据处理示例类。
 * 该类演示了如何通过多线程批量处理数据,将数据集分割成多个部分,每个部分由一个单独的线程进行处理。
 * @author lhj
 * @date 2024/04/26
 */
public class BatchDataProcessingExample {

    /**
     * 程序的主入口函数。
     * @param args 命令行参数(未使用)
     * @throws InterruptedException 如果线程在等待时被中断,则抛出此异常。
     */
    public static void main(String[] args) throws InterruptedException {
        // 初始化数据处理参数
        int dataSize = 1_000_000; // 需要处理的数据量
        int batchSize = 100_000; // 每个线程处理的数据量
        int threadCount = (dataSize + batchSize - 1) / batchSize; // 根据数据量和批量大小计算所需线程数
        System.out.println("需要启动" + threadCount + "个线程处理数据");

        // 模拟数据集
        List<Integer> data = new ArrayList<>(dataSize);
        for (int i = 0; i < dataSize; i++) {
            data.add(i);
        }

        // 使用CountDownLatch来同步线程
        CountDownLatch latch = new CountDownLatch(threadCount);

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

        // 分配任务到线程池
        for (int i = 0; i < threadCount; i++) {
            int start = i * batchSize;
            int end = Math.min(start + batchSize, dataSize);
            List<Integer> subList = data.subList(start, end);
            executor.submit(new DataProcessor(subList, latch));
        }

        // 等待所有任务完成
        latch.await();
        System.out.println("所有数据处理完成");

        // 关闭线程池
        executor.shutdown();
    }

    /**
     * 数据处理任务类,实现了Runnable接口。
     */
    static class DataProcessor implements Runnable {
        private final List<Integer> dataList; // 待处理的数据列表
        private final CountDownLatch latch; // 线程同步的计数器

        /**
         * DataProcessor 构造函数。
         * @param dataList 待处理的数据列表。
         * @param latch 线程同步的计数器。
         */
        public DataProcessor(List<Integer> dataList, CountDownLatch latch) {
            this.dataList = dataList;
            this.latch = latch;
        }

        /**
         * 执行数据处理的方法。
         */
        @Override
        public void run() {
            processData(dataList);
            // 任务完成,计数器减一
            latch.countDown();
            System.out.println("当前线程"+ Thread.currentThread().getName() +"完成数据处理");
        }

        /**
         * 示例数据处理方法。
         * @param sublist 待处理的数据子列表。
         */
        private void processData(List<Integer> sublist) {
            // 简化处理逻辑,仅打印处理的数据范围
            System.out.println("线程 " + Thread.currentThread().getName() + " 正在处理数据范围: " + sublist.get(0) + " 到 " + sublist.get(sublist.size() - 1));
            // 可以在此处添加实际的数据处理逻辑
        }
    }
}


Java中,通过`ExecutorService`接口创建的线程池提供了两种主要的方法来提交任务:`submit()`和`execute()`。这两种方法都可以用来执行`Runnable`或`Callable`任务,但它们之间存在一些差异:

1. **execute()**- **参数**:接受一个`Runnable`类型的任务。
   - **返回值**:`void`,也就是说它不返回任何结果。
   - **异常处理**:它不提供直接获取任务执行时抛出异常的机制。如果任务执行期间抛出了异常,它会被传递给线程池的`uncaughtExceptionHandler`处理,而不是直接暴露给调用者。
   - **用途**:通常用于不需要关注任务执行结果的场景,或者通过其他方式(如Future、回调等)来处理结果或异常。

2. **submit()**- **参数**:可以接受`Runnable`或`Callable`类型的任务。如果传入的是`Callable`,那么`submit()`会返回一个`Future`对象。
   - **返回值**:对于`Runnable`,返回一个表示任务执行完成的`Future<Void>`;对于`Callable`,返回一个`Future<T>`,其中`T`是`Callable`任务返回的结果类型。
   - **异常处理**:如果任务执行期间抛出了异常,这个异常会被封装进返回的`Future`对象中,调用者可以通过`Future.get()`方法来获取异常或结果,从而可以更精细地控制异常处理逻辑。
   - **用途**:适用于需要获取任务执行结果或需要处理任务执行过程中可能抛出异常的场景。`Future`提供了检查任务是否完成、取消任务以及获取结果的方法。

**总结**- 如果你不需要关心任务的执行结果,或者任务没有结果需要返回,可以使用`execute()`。
- 如果你需要获得任务的执行结果,或者需要能够取消任务、检查任务状态等高级功能,应该使用`submit()`,尤其是当你提交的是`Callable`任务时。通过`submit()`得到的`Future`对象为你提供了更多的灵活性和控制力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/578732.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】HTTP协议 — 特点

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 学习目标​ 一、请求与响应 1.服务器和客户端 二、不保存状态 1.不保存状态的协议 三、资源定位 1.URI&#xff08;统一资源标识符&#xff09; 四、请求方法 1.请求方法 五…

代码随想录算法训练营Day10 | 232.用栈实现队列、225. 用队列实现栈

232.用栈实现队列 题目&#xff1a;请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除…

Git的操作和使用

一、基本操作 1、创建git本地仓库 &#xff08;1&#xff09;创建目录&#xff1a;mkdir gitcode &#xff08;2&#xff09;进入目录&#xff1a;cd gitcode/ &#xff08;3&#xff09;查询目录内容&#xff1a;ls &#xff08;4&#xff09;在当前目录下创建git本地仓库…

数据结构(七)---二叉树

目录 一.树的基本概念 二.树的性质 三.二叉树 1.二叉树的基本概念 2.特殊的二叉树 &#xff08;1&#xff09;满二叉树 &#xff08;2&#xff09;完全二叉树 &#xff08;3&#xff09;二叉排序树 &#xff08;4&#xff09;平衡二叉树 3.二叉树的性质 4.完全二叉树…

CC软件防火墙和WEB应用防火墙哪个好

本文将从CC软件防火墙的定义、原理、功能以及应用方面进行全面探讨&#xff0c;旨在加深对CC软件防火墙的理解&#xff0c;并推动网络安全意识的普及。以及WEB应用防火墙二者之间的对比。让用户更了解两个形态产品并作出选择。 第一部分&#xff1a;CC软件防火墙的定义和原理 …

北京小米智能工厂

小米工厂智能化 小米集团昌平区的小米智能工厂二期&#xff0c;成为引领智能化制造的重要一环。这座工厂计划打造成为京津冀地区智能制造示范工厂和全球级的“灯塔工厂”。 工厂位于小米未来产业园区&#xff0c;占地81000平方米&#xff0c;年产能可达千万台智能手机&#xff…

创新指南 | 2024年企业如何十步打造最佳的数字化营销策略组合

营销是一个动态且不断变化的领域。顶级的数字营销策略随着消费者和技术趋势的变化而变化。这就是为什么每个公司都需要一个经过良好规划并具有明确里程碑和目标的营销策略。一旦你有了正确的计划&#xff0c;你实现为业务设定的目标的可能性就会大大增加。这意味着&#xff0c;…

提交链码-编辑前后端,调用链码功能

一 . 链码介绍 1.什么链码&#xff1f; • 链码是一段用 Go、Node.js 或者 Java 实现了规定接口的程序。链码在安全的Docker容器中运行&#xff0c; 与背书节点的进程隔离。通过应用程序提交的交易&#xff0c;链码初始化和管理账本状态。• 链码通常处理网络成员协商达成的业…

全网都在找的python+requests接口自动化测试框架实例详解教程

前言 Python是一种功能强大的编程语言&#xff0c;它可以用于自动化测试&#xff0c;特别是接口自动化测试。许多Python库都可以用于接口自动化测试&#xff0c;其中requests库是其中最受欢迎的库之一。 requests库可以用于发送HTTP请求并获取服务器响应&#xff0c;从而轻松…

spring常用注解(五)lombok库

一、介绍&#xff1a; 1、简介&#xff1a; Lombok是一个作用于编辑器和构建工具的 Java 库&#xff0c;可以对编写的 Java 代码进行增强&#xff0c;比如说不用再写实体类的 getter 方法&#xff0c;equals 方法而是自动生成&#xff0c;自动生成日志输出变量等等&#xff0…

uniapp 之 开发微信小程序入门详细指南

目录 配置运行设置&#xff08;编辑器的设置&#xff09;项目目录文件配置基础配置中的uniapp应用标识&#xff08;AppID&#xff09;配置微信小程序的AppID 总结 配置运行设置&#xff08;编辑器的设置&#xff09; 点击编辑器上方菜单栏 - 运行 - 运行到小程序模拟器 - 运行…

css利用transform:skew()属性画一个大屏的背景斜面四边形特效

在工作工程中需要写一个如下的大屏背景&#xff0c;是由几个斜面做成的效果 使用css transform function中的skew()方法实现画其中一个斜面&#xff0c;然后调整背景色实现 写一个div <div class"skew_container test-2"><div class"skew_container_it…

【Linux进程】守护进程

【Linux进程】守护进程 目录 【Linux进程】守护进程守护进程守护进程概念进程组和会话的概念 系统的守护进程函数 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2024.4.27 前言&#xff1a;本篇博客将会介绍守护进程&#xff0c;以及进程组和会话的概念&#xff0c;如何变成…

【信息收集】WAF防火墙识别工具Wafw00f

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、了解WAF防火墙 Web应用防护系统&#xff08;也称为&…

【Pytorch】(十三)模型部署: TorchScript

文章目录 &#xff08;十三&#xff09;模型部署: TorchScriptPytorch动态图的优缺点TorchScriptPytorch模型转换为TorchScripttorch.jit.tracetorch.jit.scripttrace和script的区别总结trace 和script 混合使用保存和加载模型 &#xff08;十三&#xff09;模型部署: TorchScr…

基于java+springboot+vue实现的医疗挂号管理系统(文末源码+Lw)203

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对医疗挂号信息管理的提升&#x…

Pytorch 之torch.nn初探 卷积--Convolution Layers

任务描述 本关任务&#xff1a; 本关提供了一个Variable 类型的变量input&#xff0c;按照要求创建一 Conv1d变量conv&#xff0c;对input应用卷积操作并赋值给变量 output&#xff0c;并输出output 的大小。 相关知识 卷积的本质就是用卷积核的参数来提取原始数据的特征&a…

OpenHarmony语言基础类库【@ohos.util.Stack (线性容器Stack)】

ohos.util.Stack (线性容器Stack) Stack基于数组的数据结构实现&#xff0c;特点是先进后出&#xff0c;只能在一端进行数据的插入和删除。 Stack和[Queue]相比&#xff0c;Queue基于循环队列实现&#xff0c;只能在一端删除&#xff0c;另一端插入&#xff0c;而Stack都在一…

[Qt的学习日常]--信号和槽

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习&#xff…

PyQt6 优化操作:建立侧边栏,要求可拖拽改变宽度,可用按钮控制侧边栏的展开和收起

1. 官方文档 QSplitter — PyQt Documentation v6.6.0 2. 效果展示 可拖拽改变宽度比例 点击按钮快速收起或展开侧边栏 点击按钮&#xff0c;侧边栏收起&#xff0c;同时按钮图标变为向左箭头 (对应展开功能)&#xff0c;再次点击按钮&#xff0c;侧边栏展开&#xff0c;同…
最新文章