如果映射文件数据完全驻留在物理内存中,那么并行读取数据有什么好处,例如通过定义具有开始/结束字节的段数并且每个段都有单独的线程?目标是允许频繁快速读取大二进制文件中的数据。
我一直在做一些测试(Java NIO),其中每个线程(使用4个线程进行测试)都可以访问mmap的引用,但由于每个线程都在mmaped文件中更改内部指针以读取下一组字节,因此不会# 39;看起来很安全。我考虑过为每个线程将文件分成4个mmaped块?
更新: 为了给出更多的上下文,我最后要做的是拥有一个数据结构,该数据结构将引用mmaped文件的数量,以便那些引用可以提供给某些函数,这些函数将对值进行循环扫描测试并将它们放入进入字节缓冲区。
更新: 这是针对只读文件的。
答案 0 :(得分:1)
您可以为每个线程创建不同的FileChannel。每个线程将读取不同的部分。
正如documentation所说,FileChannels是线程安全的。
您的代码将是这样的
package nio;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class HughTest {
public static void main(String[] args) {
try (FileChannel inChannel = new RandomAccessFile("file_Path", "r").getChannel()){
// TODO Change in each thread the chunk size to read
long fileSize = inChannel.size();
ByteBuffer buffer = ByteBuffer.allocate((int) fileSize);
inChannel.read(buffer);
buffer.flip();
// Do what you want
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
此代码在唯一线程中读取文件,您可以在可运行的类中调整代码,并在构造函数或其他位置传递FileChannel大小以并行读取整个文件,如此问题中所述:Can I seek a file from different threads independently using FileChannel?
<强>更新强>
不幸的是,MappedByteBuffer不是线程安全的,因为它是Buffer的子类,你可以在这里看到:Does memory mapped file support concurrent get/put?所以你必须使用同步机制才能并行执行。
一种方法是以时间方式复制整个文件(这样可以确保永远不会修改文件),然后使用像这样的可运行实现
private class ThreadFileRead implements Runnable {
private final long ini;
private final long end;
public ThreadFileRead(long ini, long end) {
this.ini = ini;
this.end = end;
}
@Override
public void run() {
MappedByteBuffer out = null;
try {
out = new RandomAccessFile("FILEPATH", "r").
getChannel().map(FileChannel.MapMode.READ_ONLY, ini, end);
for (long i = ini; i < end; i++)
{
// do work
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}