Чтение одного файла с помощью Multiple Thread: должно ли ускоряться?
Я читаю файл, который содержит 500000 строк. Я тестирую, чтобы увидеть, как несколько потоков ускоряют процесс....
private void multiThreadRead(int num){
for(int i=1; i<= num; i++) {
new Thread(readIndivColumn(i),""+i).start();
}
}
private Runnable readIndivColumn(final int colNum){
return new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
try {
long startTime = System.currentTimeMillis();
System.out.println("From Thread no:"+colNum+" Start time:"+startTime);
RandomAccessFile raf = new RandomAccessFile("./src/test/test1.csv","r");
String line = "";
//System.out.println("From Thread no:"+colNum);
while((line = raf.readLine()) != null){
//System.out.println(line);
//System.out.println(StatUtils.getCellValue(line, colNum));
}
long elapsedTime = System.currentTimeMillis() - startTime;
String formattedTime = String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes(elapsedTime),
TimeUnit.MILLISECONDS.toSeconds(elapsedTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(elapsedTime))
);
System.out.println("From Thread no:"+colNum+" Finished Time:"+formattedTime);
}
catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("From Thread no:"+colNum +"===>"+e.getMessage());
e.printStackTrace();
}
}
};
}
private void sequentialRead(int num){
try{
long startTime = System.currentTimeMillis();
System.out.println("Start time:"+startTime);
for(int i =0; i < num; i++){
RandomAccessFile raf = new RandomAccessFile("./src/test/test1.csv","r");
String line = "";
while((line = raf.readLine()) != null){
//System.out.println(line);
}
}
long elapsedTime = System.currentTimeMillis() - startTime;
String formattedTime = String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes(elapsedTime),
TimeUnit.MILLISECONDS.toSeconds(elapsedTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(elapsedTime))
);
System.out.println("Finished Time:"+formattedTime);
}
catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
public TesterClass() {
sequentialRead(1);
this.multiThreadRead(1);
}
при num = 1 я получаю следующий результат:
Время начала:1326224619049
Законченное время: 2 минуты, 14 секунд
Последовательное чтение ENDS...........
Многопоточное чтение начинается:
Из темы №: 1 Время начала:1326224753606
Из темы №: 1 Закончено Время: 2 мин 13 с
Многопоточность читать ENDS.....
при num = 5 я получаю следующий результат:
formatted Time:10 min, 20 sec
Sequential read ENDS...........
Multi-Thread read starts:
From Thread no:1 Start time:1326223509574
From Thread no:3 Start time:1326223509574
From Thread no:4 Start time:1326223509574
From Thread no:5 Start time:1326223509574
From Thread no:2 Start time:1326223509574
From Thread no:4 formatted Time:5 min, 54 sec
From Thread no:2 formatted Time:6 min, 0 sec
From Thread no:3 formatted Time:6 min, 7 sec
From Thread no:5 formatted Time:6 min, 23 sec
From Thread no:1 formatted Time:6 min, 23 sec
Multi-Thread read ENDS.....
Мой вопрос: не должно ли многопоточное чтение занимать ок. 2,13 сек? Не могли бы вы объяснить, почему с многопоточным решением это занимает слишком много времени?
Заранее спасибо.
3 ответа
Причина, по которой вы наблюдаете замедление при параллельном чтении, заключается в том, что магнитной головке жесткого диска необходимо искать следующую позицию чтения (около 5 мс) для каждого потока. Таким образом, чтение с несколькими потоками эффективно отскакивает диск между поисками, замедляя его. Единственный рекомендуемый способ чтения файла с одного диска - это последовательное чтение с одним потоком.
Поскольку чтение файла в основном ожидает дискового ввода-вывода, у вас есть проблема, что диск не будет вращаться быстрее только потому, что он используется многими потоками:)
Чтение из файла является по своей сути последовательным процессом, не предполагающим кэширования, то есть существует ограничение на скорость, с которой вы можете извлекать данные из файла. Даже без блокировок файлов (т. Е. Открытия файла только для чтения) все потоки после 1-го будут просто блокировать чтение на диске, поэтому вы заставляете все остальные потоки ждать, и тот из них, который становится активным, когда становятся доступными данные, обрабатывает следующий блок