繁体   English   中英

用Java读取大文件

[英]Reading huge file in Java

我读了一个巨大的File (近500万行)。 每行包含Date和一个Request ,我必须在具体的** Date **之间解析Requests。 我使用BufferedReader读取File直到开始Date然后开始解析行。 我可以使用Thread来解析行吗,因为这会花费很多时间?

并行处理许多小任务的一个好方法是用FutureTask包装每个任务的处理,然后将每个任务传递给ThreadPoolExecutor来运行它们。 应该使用系统可用的CPU内核数来初始化执行程序。

当您调用executor.execute(future) ,将来将排队等待后台处理。 为了避免创建和销毁过多的线程,ScheduledThreadPoolExecutor将仅创建您指定的数量的线程,并一个接一个地执行期货。

要检索future的结果,请调用future.get() 当未来尚未完成(或什至尚未开始)时,此方法将冻结直到完成。 但是当您等待时,其他期货也会在后台执行。

请记住,当您不再需要executor.shutdown()时,请确保它终止了它在后台的线程,否则该线程将一直保持到Keepalive时间到期或被垃圾回收为止。

tl; dr伪代码:

 create executor
 for each line in file
     create new FutureTask which parses that line
     pass future task to executor
     add future task to a list
 for each entry in task list
     call entry.get() to retrieve result
 executor.shutdown()

您的问题尚不完全清楚,但是听起来好像您每次客户请求数据时都在重新解析500万行的文件。 您当然可以通过抛出更多的线程和更多的CPU内核来解决该问题,但是更好的解决方案是通过消除重复的工作来提高应用程序的效率。

在这种情况下,您应该重新设计应用程序,以避免在每次请求时重新解析整个文件。 理想情况下,您应该将数据存储在数据库或内存中,而不是在每次请求时都处理平面文本文件。 然后根据请求在数据库或内存数据结构中查找信息。

如果无法完全消除500万行的文件,则可以定期重新检查大文件的更改,跳过/查找到最后一条已解析的记录的末尾,然后仅解析新记录并更新数据库或内存中的数据结构体。 所有这些都可以选择在单独的线程中完成。

首先,500万行(每行1000个字符)只有5Gb,这对于JVM而言并不一定是禁止的。 如果这实际上是一个命中率很高的关键用例,那么购买更多的内存几乎肯定是正确的选择。

其次,如果不可能的话,最有可能正确的做法是根据日期构建有序地图。 因此,每个日期都是地图中的键,并且指向包含请求的行号列表。 然后,您可以直接转到相关的行号。

形式的东西

HashMap<Date, ArrayList<String>> ()

会很好。 那应该具有5,000,000 * 32/8字节= 20Mb的内存使用量,应该没问题。

您还可以使用FileChannel类在从在线跳转到另一行时保持I / O句柄打开。 这允许内存映射。

参见http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html

还有http://en.wikipedia.org/wiki/Memory-mapped_file

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM