2015-11-22 4 views
3

Если отображаемые данные файла полностью резидентны в физической памяти, будет ли какая-либо польза от чтения данных параллельно, например, путем определения количества секций с байтом начала/конца и иметь отдельный поток, работающий с каждой секцией? Цель состоит в том, чтобы обеспечить частые быстрые чтения данных из большого двоичного файла.Чтение данных из файла с отображением памяти параллельно?

Я провел несколько тестов (Java NIO), где каждый поток (тестирование с 4 потоками) имеет доступ к ссылке mmap, но поскольку каждый поток изменяет внутренний указатель в mmaped-файле, чтобы читать следующий набор байтов, это не кажется безопасным. Я думаю о разделении файла на 4 мм куска для каждой нити?

UPDATE: Чтобы предоставить больше контекста, в конечном счете, то, что я собираюсь сделать, это структура данных, которая будет содержать ссылку на число mmaped файлов, чтобы затем эта ссылка могла быть предоставлена ​​некоторой функции, которая будет выполнять проверку сканирования цикла для значений и помещения их в буфер байтов.

ОБНОВЛЕНИЕ: Это файлы только для чтения.

ответ

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?

UPDATE

К сожалению MappedByteBuffer не поточно как это су bclass of 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(); 
      } 

     } 

    } 
+0

Это не кажется используйте mmap. Разве этот подход не требовал бы чтения с диска при каждом вызове метода read? –

+0

Да ... в каждом вызове этот код будет читать с диска ... Позвольте мне посмотреть, можно ли это объединить с mmap –

+0

Спасибо, это полезно. Я думаю, в конце концов, может быть, было бы неплохо разделить файл на столько миллиметров, сколько нужно потокам, хранить ссылки на них, а затем каждый раз, когда мне нужно читать, передавайте эти ссылки mmap на runnable. Имеет ли это смысл? –