用Java读取大文件

时间:2014-07-07 15:16:40

标签: java bufferedreader

我读了一个巨大的File(近500万行)。每行包含日期请求,我必须在具体的**日期**之间解析请求。我使用BufferedReader来阅读File,直到开始Date,然后开始解析行。我可以使用Thread来解析行,因为它需要花费很多时间吗?

3 个答案:

答案 0 :(得分:0)

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

当您致电executor.execute(future)时,将来会排队等待后台处理。为了避免创建和销毁太多线程,ScheduledThreadPoolExecutor将只创建您指定的线程并一个接一个地执行期货。

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

请记住,当您不再需要它时,请调用executor.shutdown(),以确保它终止其保留的后台线程,直到保持活动时间到期或被垃圾收集。

tl; dr pseudocode:

 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()

答案 1 :(得分:0)

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

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

如果你无法完全消除500万行文件,你可以定期重新检查大文件的变化,跳过/搜索到最后一条被解析的记录的末尾,然后只解析新记录并更新数据库或者 - 内存数据结构。这可以全部在一个单独的线程中完成。

答案 2 :(得分:0)

首先,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