Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java—并行读取二进制文件_Java_Multithreading_File Io_Random Access - Fatal编程技术网

Java—并行读取二进制文件

Java—并行读取二进制文件,java,multithreading,file-io,random-access,Java,Multithreading,File Io,Random Access,我有一个包含信息块的二进制文件(以后我将它们称为数据包)。每个数据包由一个固定长度的报头和一个可变长度的正文组成。我必须根据数据包头本身来确定正文的长度。我的任务是从文件中读取这些数据包,并对它们执行一些操作。目前,我正在执行以下任务: 将文件作为随机访问文件打开并转到特定的开始位置(用户指定的开始位置)。从这个位置读取第一个数据包。执行特定操作 然后在一个循环中 阅读下一个数据包 执行我的操作 这一直持续到我到达文件末尾标记 您可以猜到,当文件大小很大时,连续读取每个数据包并对其进行处

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

  • 将文件作为随机访问文件打开并转到特定的开始位置(用户指定的开始位置)。从这个位置读取第一个数据包。执行特定操作
  • 然后在一个循环中
    • 阅读下一个数据包
    • 执行我的操作 这一直持续到我到达文件末尾标记
您可以猜到,当文件大小很大时,连续读取每个数据包并对其进行处理是一件耗时的事情。我想以某种方式并行化此操作,即数据包生成操作,并将其放入某个阻塞队列中,然后从队列中并行检索每个数据包并执行我的操作


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

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

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

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


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

如果您使用的是带盘片的磁盘(即,不是SSD)那么,让多个线程读取文件是没有意义的,因为您所要做的就是重击磁盘,导致磁盘臂引入毫秒延迟。如果你有一个SSD,它是一个不同的故事,你可以平行阅读

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

  • 等待共享信号量“a”(已初始化为某个数字,该数字将是您的“最大缓冲数据包”计数)
  • 锁定共享对象
  • 将数据包附加到LinkedList
  • 向另一个共享信号量“B”发送信号(该信号量跟踪缓冲区中的数据包计数)
然后,您可以让许多其他线程执行以下操作:

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

这将确保您以一个连续的顺序条带化数据包,以尽可能快的速度读取数据包(从盘片磁盘),并确保您在不进行任何轮询的情况下一次处理多个数据包。

每个数据包头在文件中的位置(在第一个数据包头之后)取决于前一个数据包的大小吗?@Ted:不太可能。我根据读取的字节的特定签名检测下一个数据包头的开始。它会出现在前一个数据包结束后的某个地方,但不会出现在任何特定的位置。这听起来像是一个简单的内存映射。如何使用它来发现存储在非标准字节边界上的数据包?如果报头有长度,您至少可以跳过数据包-如果没有,您可以进行并行扫描并调整!与使用文件指针和advance+1相比,将块预加载到内存中并扫描它们肯定是一种更快的方法,尽管现代SSD可能会使并行读取连续文件的速度比顺序读取速度快得多。@sarnold:可能是这样。我没有足够的经验来描述SSD架构:P+1对于阻止多线程进行读取,这对性能非常重要。@tskuzzy:谢谢你的建议。我想并行处理数据包将是最好的进步!谢谢@AnthonyM的建议!我猜你们和前面的答案指向同一个方向,即并行处理数据包,而不是并行访问文件。