Java - 并行读取二进制文件

时间:2012-06-19 22:18:16

标签: java multithreading file-io random-access

我有一个二进制文件,其中包含信息块(我将它们称为数据包,因此)。每个数据包由一个固定长度的头和一个可变长度的主体组成。我要从包头本身确定身体的长度。我的任务是从文件中读取这些数据包并对它们执行一些操作。目前我正在执行以下任务:

  • 将文件作为随机访问文件打开并转到特定的开始位置(用户指定的起始位置)。从这个位置读取第一个数据包。执行特定操作
  • 然后循环
    • 阅读下一个数据包
    • 执行我的操作 这一直持续到文件标记结束为止。

正如您所猜测的,当文件大小很大时,连续读取每个数据包并进行处理是一件非常耗时的事情。我想以某种方式并行化这个操作,即数据包生成操作,并将其放入一些阻塞队列,然后从队列中并行检索每个数据包并执行我的操作。

有人可以建议我如何并行生成这些数据包?

3 个答案:

答案 0 :(得分:5)

由于我假设文件位于单个驱动器中,因此您应该只在文件中按顺序读取一个线程。读取文件受到IO速度的限制,因此在CPU中并行化是没有意义的。实际上,非顺序读取实际上会显着降低性能,因为常规硬盘设计用于顺序IO。对于它读入的每个数据包,它应该将该对象放入一个线程安全的队列中。

现在您可以开始并行处理数据包了。创建多个线程,让每个线程从队列中读取数据包。每个线程都应该进行处理并将其放入一些“已完成”的队列中。

一旦IO线程读完文件,就应该设置一个标志,以便在队列为空时工作线程停止。

答案 1 :(得分:3)

如果您正在使用带盘片的磁盘(即不是SSD),那么没有必要让多个线程读取该文件,因为您只需要扫描磁盘,导致磁盘臂引入毫秒延迟。如果你有一个不同的故事,你可以将读数平行化。

相反,您应该有一个线程从文件中读取数据并创建数据包,然后执行以下操作:

  • 等待共享信号量'A'(已初始化为某个数字,这将是您的'最大缓冲数据包'计数)
  • 锁定共享对象
  • 将数据包附加到LinkedList
  • 发信号通知另一个共享信号量'B'(这个是跟踪缓冲区中数据包的计数)

然后你可以让许多其他线程执行以下操作:

  • 等待'B'信号量(以确保有待处理的数据包)
  • 锁定共享对象
  • 对LinkedList执行getFirst()并将数据包存储在本地变量
  • 信号信号量'A'允许另一个数据包进入缓冲的数据包列表

这将确保您通过一个连续的序列对它们进行快速读取(从盘片磁盘),并确保您一次处理多个数据包而不进行任何轮询。

答案 2 :(得分:0)

我想已知的快速方法是使用java.nio.MappedByteBuffer