Java多線程讀取大文件


轉載:http://www.cnblogs.com/metoy/p/4470418.html

前言

  今天是五一假期第一天,按理應該是快樂玩耍的日子,但是作為一個北漂到京師的開發人員,實在難想出去那玩耍。好玩的地方比較遠,近處又感覺沒意思。於是乎,閑着寫篇文章,總結下昨天寫的程序吧。

  昨天下午朋友跟我聊起,他說有個需求,需要把上G的txt文件讀取寫入到數據庫。用普通的io結果自然是OOM了,所以果斷用NIO技術。為了提高速度,自然還得用上多線程技術。

  接下來就介紹一下實現思路以及相關的知識點。

內容

     一、對文件分區

        為了充分利用多線程讀取,就需要把文件划分成多個區域,供每個線程讀取。那么就需要有一個算法來計算出每個線程讀取的開始位置和結束位置。那么首先根據配置的線程數和文件的總長度計,算出每個線程平均分配的讀取長度。但是有一點,由於文件是純文本文件,必須按行來處理,如果分割點在某一行中間,那么這一行數據就會被分成兩部分,分別由兩個線程同時處理,這種情況是不能出現的。所以各個區域的結束點上的字符必須是換行符。第一個區域的開始位置是0,結束位置首先設為(文件長度/線程數),如果結束點位置不是換行符,就只能加1,直到是換行符位置。第一個區域的結束位置有了,自然我們就能求出第二個區域的開始位置了,同理根據上邊算法求出第二個區域的結束位置,然后依次類推第三個、第四個......

        上邊的算法中,第一個區域的結束位置定了,才能有第二個區域的開始位置,第二個區域的結束位置定了,才能有第三個區域的開始位置,依次這么下去。照這種規律,自然地想到的是用遞歸來解決。(詳情看源碼

    二、內存文件映射

      簡單說一下內存文件映射:

內存文件映射,簡單地說就是將文件映射到內存的某個地址上。
要理解內存文件映射,首先得明白普通方式讀取文件的流程:
     首先內存空間分為內核空間和用戶空間,在應用程序讀取文件時,底層會發起系統調用,由系統調用將數據先讀入到內核空間,然后再將數據拷貝到應用程序的用戶空間供應用程序使用。這個過程多了一個從內核空間到用戶空間拷貝的過程。
 
如果使用內存文件映射,文件會被映射到物理內存的某個地址上(不是數據加載到內存),此時應用程序讀取文件的地址就是一個內存地址,而這個內存地址會被映射到了前面說到的物理內存的地址上。應用程序發起讀之后,如果數據沒有加載,系統調用就會負責把數據從文件加載到這塊物理地址。應用程序便可以讀取到文件的數據。省去了數據從內核空間到用戶空間的拷貝過程。所以速度上也會有所提高。

      在我的讀取大文件的實現中,就是用了Java的內存映射API,這樣我們就可以在要讀取某個地址時再將內容加載到內存。不需要一下子全部將內容加載進來。

總結

  以上就是我主要用到的思路和一些技術點吧。可能存在某些表達不清楚的地方,望大神勿噴^_^

  具體實現請參考代碼吧,這里是代碼的地址(Java讀取大文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM