首先來看一下多線程下載的原理。多線程下載就是將同一個網(wǎng)絡(luò)上的原始文件根據(jù)線程個數(shù)分成均等份,然后每個單獨(dú)的線程下載對應(yīng)的一部分,然后再將下載好的文件按照原始文件的順序“拼接”起來就構(gòu)
成了完整的文件了。這樣就大大提高了文件的下載效率。對于文件下載來說,多線程下載是必須要考慮的環(huán)節(jié)。

      多線程下載大致可分為以下幾個步驟:

       一.獲取服務(wù)器上的目標(biāo)文件的大小
              顯然這一步是需要先訪問一下網(wǎng)絡(luò),只需要獲取到目標(biāo)文件的總大小即可。目的是為了計(jì)算每個線程應(yīng)該分配的下載任務(wù)。

      二. 在本地創(chuàng)建一個跟原始文件同樣大小的文件
             在本地可以通過RandomAccessFile 創(chuàng)建一個跟目標(biāo)文件同樣大小的文件,該api 支持文件任意位置的讀寫操作。這樣就給多線程下載提供了方便,每個線程只需在指定起始和結(jié)束腳標(biāo)范圍內(nèi)寫數(shù)據(jù)即可。

      三.計(jì)算每個線程下載的起始位置和結(jié)束位置
             我們可以把原始文件當(dāng)成一個字節(jié)數(shù)組,每個線程只下載該“數(shù)組”的指定起始位置和指定結(jié)束位置之間的部分。在第一步中我們已經(jīng)知道了“數(shù)組”的總長度。因此只要再知道總共開啟的線程的個數(shù)就好計(jì)算每個線程要下載的范圍了。每個線程需要下載的字節(jié)個數(shù)(blockSize)=總字節(jié)數(shù)(totalSize)/線程數(shù)(threadCount)。       假設(shè)給線程按照0,1,2,3...n 的方式依次進(jìn)行編號,那么第n 個線程下載文件的范圍為:
               起始腳標(biāo)startIndex=n*blockSize。
              結(jié)束腳標(biāo)endIndex=(n-1)*blockSize-1。
            考慮到totalSize/threadCount 不一定能整除,因此對已最后一個線程應(yīng)該特殊處理,最后一個線程的起始腳標(biāo)計(jì)算公式不變,但是結(jié)束腳標(biāo)為endIndex=totalSize-1即可。
     四.開啟多個子線程開始下載
            在子線程中實(shí)現(xiàn)讀流操作,將conn.getInputStream()讀到RandomAccessFile中。