Java多线程读取大文件

前言

  有个需求,需要把上G的txt文件读取写入到数据库。用普通的io结果自然是OOM了,所以果断用NIO技术。为了提高速度,自然还得用上多线程技术。

  接下来就介绍一下实现思路以及相关的知识点。

 

内容

一、对文件分区

  为了充分利用多线程读取,就需要把文件划分成多个区域,供每个线程读取。那么就需要有一个算法来计算出每个线程读取的开始位置和结束位置。那么首先根据配置的线程数和文件的总长度计,算出每个线程平均分配的读取长度。但是有一点,由于文件是纯文本文件,必须按行来处理,如果分割点在某一行中间,那么这一行数据就会被分成两部分,分别由两个线程同时处理,这种情况是不能出现的。所以各个区域的结束点上的字符必须是换行符。第一个区域的开始位置是0,结束位置首先设为(文件长度/线程数),如果结束点位置不是换行符,就只能加1,直到是换行符位置。第一个区域的结束位置有了,自然我们就能求出第二个区域的开始位置了,同理根据上边算法求出第二个区域的结束位置,然后依次类推第三个、第四个......

  上边的算法中,第一个区域的结束位置定了,才能有第二个区域的开始位置,第二个区域的结束位置定了,才能有第三个区域的开始位置,依次这么下去。照这种规律,自然地想到的是用递归来解决。(详情看源码

 

二、内存文件映射

简单说一下内存文件映射:

  内存文件映射,简单地说就是将文件映射到内存的某个地址上。

要理解内存文件映射,首先得明白普通方式读取文件的流程:

  首先内存空间分为内核空间和用户空间,在应用程序读取文件时,底层会发起系统调用,由系统调用将数据先读入到内核空间,然后再将数据拷贝到应用程序的用户空间供应用程序使用。这个过程多了一个从内核空间到用户空间拷贝的过程。

 

  如果使用内存文件映射,文件会被映射到物理内存的某个地址上(不是数据加载到内存),此时应用程序读取文件的地址就是一个内存地址,而这个内存地址会被映射到了前面说到的物理内存的地址上。应用程序发起读之后,如果数据没有加载,系统调用就会负责把数据从文件加载到这块物理地址。应用程序便可以读取到文件的数据。省去了数据从内核空间到用户空间的拷贝过程。所以速度上也会有所提高。

 

总结

  在我的读取大文件的实现中,就是用了Java的内存映射API,这样我们就可以在要读取某个地址时再将内容加载到内存。不需要一下子全部将内容加载进来。

  代码的地址(Java读取大文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值