2

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

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

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

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

4

3 回答 3

5

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

现在您可以开始并行处理数据包。创建多个线程并让它们分别从队列中读取数据包。每个线程都应该进行处理并将其放入某个“完成”队列中。

一旦 IO 线程读完文件,就应该设置一个标志,这样一旦队列为空,工作线程就会停止。

于 2012-06-19T22:30:18.840 回答
3

如果您使用的是带有盘片的磁盘(即不是 SSD),那么让多个线程读取文件是没有意义的,因为您所要做的就是破坏磁盘,从而导致磁盘臂引入毫秒延迟。如果您有 SSD,那就另当别论了,您可以并行读取。

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

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

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

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

这将确保您通过以一个连续的顺序对数据包进行条带化,从而尽可能快地(从盘片磁盘)读取数据包,并确保您一次处理多个数据包而无需任何轮询。

于 2012-06-19T22:35:14.183 回答
0

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

于 2012-06-19T22:24:28.970 回答