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