当前位置:网络安全 > Java多线程读取大文件

Java多线程读取大文件

  • 发布:2023-10-11 05:16

-->

前言

  今天是五一假期的第一天。这本来应该是一个热闹、好玩的日子,但作为一个和北漂一起在北京的开发者,实在很难想到去那里玩。好玩的地方很远,但近处却觉得无聊。那么,等我有空了,就写一篇文章,总结一下我昨天写的程序吧。

  我的朋友昨天下午跟我说话。他说他有一个需要将G上的txt文件读写到数据库中。使用普通io的结果自然是OOM,所以我果断使用NIO技术。为了提高速度,自然要使用多线程技术。

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

内容

     1。分区文件

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

        上述算法中,只有确定了第一个区域的结束位置才能确定第二个区域的开始位置,只有确定了第二个区域的结束位置才能确定第三个区域的开始位置予以确定,等等。下去。根据这个规则,自然想到的就是用递归来解决。 (详情见源码)

    2。内存文件映射

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

内存文件映射简单来说就是将文件映射到内存中的某个地址。
要了解内存文件映射,首先要了解正常读取文件的过程:
首先,内存空间分为内核空间和用户空间。当应用程序读取文件时,底层会发起系统调用。系统调用首先会将数据读入内核空间,然后将数据复制到应用程序的用户空间供应用。程序使用。这个过程增加了一个从内核空间复制到用户空间的过程。 如果使用内存文件映射,文件会被映射到物理内存中的某个地址(而不是将数据加载到内存中)。此时应用程序读取文件的地址就是一个内存地址,这个内存地址将会映射到上面提到的地址。到物理内存地址。应用程序发起读取后,如果没有加载数据,则系统调用将负责将数据从文件加载到该物理地址。然后应用程序可以从文件中读取数据。这消除了将数据从内核空间复制到用户空间的需要。所以速度也会得到提升。

      在我读取大文件的实现中,我使用了Java的内存映射API,这样当我们要读取某个地址时,就可以将内容加载到内存中。无需一次加载全部内容。

总结

  以上是我使用的主要思路和一些技术点。可能有表达不清楚的地方,请见谅^_^

  具体实现请参考代码。这里是代码地址(Java读取大文件)

  

        

-->

相关文章