2012-01-10 127 views
5

我正在讀取一個包含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 ...........

多線程讀開始:

自Thread NO:1開始時間:1326224753606

自Thread NO: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秒? 你能解釋一下爲什麼多線程解決方案需要花費很長時間?

在此先感謝。

+0

[Java多線程應用程序讀取單個文件]的可能重複(http://stackoverflow.com/questions/8126277/java-multi-thread-application-that-reads-a-single-file) – 2012-01-10 20:16:02

+0

除非線程寫入不同的磁盤,否則線程將無法工作,在這種情況下,兩個線程都將競爭寫入同一個文件。因此,線程在這種情況下將不起作用。 – 2012-01-10 20:16:18

+0

@TomaszNurkiewicz - 不一樣的是,每個文件使用一個線程。 – 2012-01-10 20:22:23

回答

7

由於文件的閱讀主要是等待磁盤I/O,你的磁盤將不會轉得更快只是因爲它是由許多線程:)

+1

線程/鎖定也會在其中起作用嗎? – Bhushan 2012-01-10 20:18:36

+0

可能,I/O鎖定策略將取決於Java實現和底層操作系統。 – 2012-01-10 20:26:26

+0

我正在執行相同用例的測試 - 從多個線程讀取單個文件。我發現如果底層存儲是SATA磁盤驅動器,那麼擁有多個線程可以提高性能,同時提高SAS驅動器的性能。這是因爲點對點技術還是我的測試做錯了什麼? – 2013-06-24 13:19:25

1

從文件讀取本質上是一個連續過程中的問題,假設沒有緩存,這意味着您可以從文件中檢索數據的速度有限。即使沒有文件鎖定(即,只讀文件打開文件),第1個之後的所有線程都會阻塞磁盤讀取,以便讓所有其他線程等待以及在數據可用時處於活動狀態的任何線程是處理下一個街區。

5

並行讀取時看到緩慢的原因是因爲磁性硬盤磁頭需要爲每個線程尋找下一個讀取位置(約5ms)。因此,使用多線程進行讀取會在尋求之間有效地反彈磁盤,從而減慢速度。從單個磁盤讀取文件的唯一推薦方法是使用一個線程順序讀取。

+0

感謝您的意見。即使多線程讀取需要更多時間(例如。6.2分鐘而不是2.10分鐘),仍然可以節省4/5分鐘,而我連續讀取5次(即連續讀取= 10.20分鐘;其中5個線程= 6.20分鐘) – Hasan 2012-01-11 13:41:46