当前位置: 首页 > news >正文

Java多线程并行读取多个文件(二)

目录

一、Java多线程并行读取多个文件 

二、AsynchronousFileChannel 详解 

三、异步文件读取 


一、Java多线程并行读取多个文件 

在考虑性能问题时,多线程并行读取多个文件的实现需要注意一些关键因素,以充分发挥多线程并发的优势,并避免性能瓶颈。

  1. 文件分配和任务划分: 将文件分成适当数量的块,并为每个块创建一个独立的任务。这有助于避免某一个文件或任务成为性能瓶颈。

  2. 线程池配置: 根据硬件配置和任务的性质来合理配置线程池。线程池的大小应该适应处理器核心数量、磁盘 I/O 和任务的性质。

  3. 异步 I/O: 使用 Java NIO(New I/O)库提供的异步文件 I/O 特性,以便能够在等待文件读取的同时执行其他任务。

  4. 缓存和缓冲: 使用适当的缓冲机制,例如 BufferedReader,以减少磁盘 I/O 操作的次数。合理调整缓冲区的大小。

  5. 并发数据结构: 使用 Java 并发数据结构,如 ConcurrentHashMapCopyOnWriteArrayList,以避免对共享数据结构的显式同步。

  6. 避免竞态条件: 仔细设计数据结构和共享资源的访问方式,以避免竞态条件和线程安全问题。

  7. 错误处理: 考虑并发环境下的错误处理机制,确保能够捕获和处理各个线程中的异常。

  8. 性能测试和调优: 对实际应用进行性能测试,使用性能分析工具来检测性能瓶颈,并进行适当的调优。

二、AsynchronousFileChannel 详解 

AsynchronousFileChannel 是 Java NIO 中用于进行异步文件 I/O 操作的类。它允许在文件读取或写入时执行异步操作,从而不会阻塞当前线程,提高程序的并发性能。

1、打开通道:

AsynchronousFileChannel channel = AsynchronousFileChannel.open(Path path, Set<? extends OpenOption> options, ExecutorService executor)
  • Path path: 文件路径。
  • Set<? extends OpenOption> options: 打开文件的选项,如 StandardOpenOption.READStandardOpenOption.WRITE
  • ExecutorService executor: 用于处理 I/O 操作的 ExecutorService,可以为 null

2、 读取文件:

Future<Integer> read(ByteBuffer dst, long position)
  • ByteBuffer dst: 存储读取数据的缓冲区。
  • long position: 从文件的指定位置开始读取。

3、写入文件: 

Future<Integer> write(ByteBuffer src, long position)
  • ByteBuffer src: 包含要写入文件的数据的缓冲区。
  • long position: 写入文件的指定位置。

4、使用 CompletionHandler 进行异步操作: 

void read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer,? super A> handler)
  • ByteBuffer dst: 存储读取数据的缓冲区。
  • long position: 从文件的指定位置开始读取。
  • A attachment: 用于传递给 CompletionHandler 的附件。
  • CompletionHandler<Integer, ? super A> handler: 处理异步操作结果的回调接口。

同样,write 方法也有类似的异步操作方法。

5、关闭通道:

void close()

 使用 AsynchronousFileChannel 进行异步文件 I/O 操作的关键点是理解异步操作的回调机制。当异步操作完成时,将调用注册的 CompletionHandler,该处理程序的 completed 方法将提供异步操作的结果。

三、异步文件读取 

ExecutorServiceAsynchronousFileChannel 进行异步文件读取的示例。以下是一个基本的示例:

package com.sl.config;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @package: com.sl.config* @author: shuliangzhao* @description:* @date 2023/11/29 22:02*/
public class AsyncFileReadExample {public static void main(String[] args) {// 文件路径列表String[] filePaths = {"D:\\aplus\\file1.txt", "D:\\aplus\\file2.txt", "D:\\aplus\\file3.txt"};// 创建线程池ExecutorService executorService = Executors.newFixedThreadPool(filePaths.length);for (String filePath : filePaths) {Path path = Paths.get(filePath);// 异步文件通道try (AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ)) {// 缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 异步读取文件fileChannel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {System.out.println(Thread.currentThread().getName());System.out.println("Read " + result + " bytes from " + path);// 处理读取的数据attachment.flip();byte[] data = new byte[attachment.limit()];attachment.get(data);System.out.println("Data: " + new String(data));// 清空缓冲区attachment.clear();// 关闭文件通道等资源try {fileChannel.close();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}});} catch (IOException e) {e.printStackTrace();}}// 关闭线程池executorService.shutdown();}
}

在这个示例中,我们创建了一个线程池(ExecutorService),然后使用 AsynchronousFileChannel 打开文件,并使用 CompletionHandler 处理异步文件读取的结果。每个文件都有一个独立的 AsynchronousFileChannelCompletionHandler。在 completed 方法中,我们处理读取的数据,然后关闭文件通道等资源。

相关文章:

  • 嘴尚绝卤味:健康卤味,未来餐饮市场的新星
  • exceljs读取el-upload上传的excle数据并转为json输出
  • 设计模式总览
  • 英伟达狂卖50万台GPU!AI爆火背后,是显卡的争夺
  • DeDeCMS v5.7 SP2 正式版 前台任意用户密码修改(漏洞复现)
  • pytorch 代码块积累
  • pycharm 创建vue并实现简易路由功能
  • LabVIEWL实现鸟巢等大型结构健康监测
  • Java零基础-switch条件语句
  • 算法设计与实现--贪心篇
  • 笔记-基于CH579M模块通过网线直连电脑进行数据收发(无需网络)
  • 什么是Daily Scrum?
  • 1038. 从二叉搜索树到更大和树 --力扣 --JAVA
  • Java内存缓存神器:Caffeine(咖啡因)
  • 松下、书客、明基护眼台灯值不值得买?热门护眼台灯真实测评!
  • 【EOS】Cleos基础
  • django开发-定时任务的使用
  • Flannel解读
  • JavaScript 基础知识 - 入门篇(一)
  • Markdown 语法简单说明
  • Mysql优化
  • python学习笔记 - ThreadLocal
  • Spring Boot MyBatis配置多种数据库
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • windows-nginx-https-本地配置
  • 闭包--闭包作用之保存(一)
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 协程
  • 学习HTTP相关知识笔记
  • 鱼骨图 - 如何绘制?
  • 怎样选择前端框架
  • Semaphore
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #QT(串口助手-界面)
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (简单) HDU 2612 Find a way,BFS。
  • (蓝桥杯每日一题)love
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .Net Remoting常用部署结构
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET分布式缓存Memcached从入门到实战
  • .NET构架之我见
  • .NET开发者必备的11款免费工具
  • :O)修改linux硬件时间
  • @Resource和@Autowired的区别
  • @vue/cli脚手架
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname