Java多線程讀取大文件

前言

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

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

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

內容

     1、對文件分區算法

        爲了充分利用多線程讀取,就須要把文件劃分紅多個區域,供每一個線程讀取。那麼就須要有一個算法來計算出每一個線程讀取的開始位置和結束位置。那麼首先根據配置的線程數和文件的總長度計,算出每一個線程平均分配的讀取長度。可是有一點,因爲文件是純文本文件,必須按行來處理,若是分割點在某一行中間,那麼這一行數據就會被分紅兩部分,分別由兩個線程同時處理,這種狀況是不能出現的。因此各個區域的結束點上的字符必須是換行符。第一個區域的開始位置是0,結束位置首先設爲(文件長度/線程數),若是結束點位置不是換行符,就只能加1,直到是換行符位置。第一個區域的結束位置有了,天然咱們就能求出第二個區域的開始位置了,同理根據上邊算法求出第二個區域的結束位置,而後依次類推第三個、第四個......數據庫

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

    2、內存文件映射線程

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

    內存文件映射,簡單地說就是將文件映射到內存的某個地址上。
    要理解內存文件映射,首先得明白普通方式讀取文件的流程:
        首先內存空間分爲內核空間和用戶空間,在應用程序讀取文件時,底層會發起系統調用,由系統調用將數據先讀入到內核空間,而後再將數據拷貝到應用程序的用戶空間供應用程序使用。這個過程多了一個從內核空間到用戶空間拷貝的過程。

    若是使用內存文件映射,文件會被映射到物理內存的某個地址上(不是數據加載到內存),此時應用程序讀取文件的地址就是一個內存地址,而這個內存地址會被映射到了前面說到的物理內存的地址上。應用程序發起讀以後,若是數據沒有加載,系統調用就會負責把數據從文件加載到這塊物理地址。應用程序即可以讀取到文件的數據。省去了數據從內核空間到用戶空間的拷貝過程。因此速度上也會有所提升。

      在個人讀取大文件的實現中,就是用了Java的內存映射API,這樣咱們就能夠在要讀取某個地址時再將內容加載到內存。不須要一會兒所有將內容加載進來。遞歸

總結

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

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

相關文章
相關標籤/搜索