摘要:原理多線程下載的原理就是將要下載的文件分成若干份,其中每份都使用一個多帶帶的線程進(jìn)行下載,這樣對于文件的下載速度自然就提高了許多??偨Y(jié)多線程的關(guān)鍵就是分配好需要下載的進(jìn)程,定位進(jìn)程下載的準(zhǔn)確位置,獲取輸入流讀取數(shù)據(jù),同時寫入到文件的相應(yīng)位置。
原理
多線程下載的原理就是將要下載的文件分成若干份,其中每份都使用一個多帶帶的線程進(jìn)行下載,這樣對于文件的下載速度自然就提高了許多。
既然要分成若干部分分工下載,自然要知道各個線程自己要下載的起始位置,與要下載的大小。所以我們要解決線程的分配與各個線程定位到下載的位置。
封裝對于多線程下載我們可以將其封裝到一個工具類中DownUtil,向其中傳入下載的鏈接、文件存儲路徑、需要下載的線程數(shù)
public DownUtil(String path, String targetFile, int threadNum) { this.path = path; this.targetFile = targetFile; this.threadNum = threadNum; downThreads = new DownThread[threadNum]; }
其中DownThread實現(xiàn)的是各個線程的下載
分配線程這里通過HttpURLConnection進(jìn)行網(wǎng)絡(luò)請求下載,通過getContentLength()方法獲取下載文件的總大小,再對其平均分配各個線程需要下載的大小。這樣就確定了下載的大小,下面就是定位到各個線程的開始位置進(jìn)行下載,這里可以使用RandomAccessFile來追蹤定位到要下載的位置,它的seek()方法可以進(jìn)行定位。下面是詳細(xì)代碼:
public void download() throws Exception { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); fileSize = conn.getContentLength(); conn.disconnect(); //需要下載的大小 int currentPartSize = fileSize / threadNum + 1; RandomAccessFile file = new RandomAccessFile(targetFile, "rw"); //設(shè)置本地文件大小 file.setLength(fileSize); file.close(); for (int i = 0; i < threadNum; i++) { //下載開始位置 int startPos = i * currentPartSize; RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw"); //定位到下載位置 currentPart.seek(startPos); //下載線程 downThreads[i] = new DownThread(startPos, currentPartSize, currentPart); downThreads[i].start(); } }線程下載
下面就是各個線程的下載DownThread,上面已經(jīng)得到了各個線程要下載的初始位置,所以可以通過獲取網(wǎng)絡(luò)請求的輸入流InputStream,通過skip()方法跳躍到指定位置進(jìn)行讀取數(shù)據(jù),再寫入到RandomAccessFile文件中。
public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) { this.startPos = startPos; this.currentPartSize = currentPartSize; this.currentPart = currentPart; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); InputStream in = conn.getInputStream(); skipFully(in, startPos); byte[] buffer = new byte[1024]; int hasRead = 0; while ((hasRead = in.read(buffer)) > 0 && length < currentPartSize) { currentPart.write(buffer, 0, hasRead); length += hasRead; } currentPart.close(); in.close(); } catch (Exception e) { e.printStackTrace(); } } }
這樣就完成了一個簡單的多線程的下載,最后調(diào)用封裝類DownUtil就可以進(jìn)行多線程下載。
總結(jié)多線程的關(guān)鍵就是分配好需要下載的進(jìn)程,定位進(jìn)程下載的準(zhǔn)確位置,獲取輸入流讀取數(shù)據(jù),同時寫入到文件的相應(yīng)位置??梢越柚?b>RandomAccessFile來進(jìn)行定位。
當(dāng)然也并非開的線程數(shù)越多下載的速度也就越快,因為線程越多對于程序處理這些線程也是一種負(fù)擔(dān),過多的話反而會降低下載的速度,所以要合理運用。
個人blog地址:https://idisfkj.github.io/arc...
關(guān)注文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/64854.html
摘要:多線程下載原理及步驟在本地創(chuàng)建一個大小跟服務(wù)器文件相同大小的臨時文件。在這里在介紹一個有關(guān)多線程下載的中的相關(guān)類隨機文件訪問類只有才有搜尋方法,而這個方法也只適用于文件。利用這個類才能實現(xiàn)文件的多線程下載。 多線程下載在我們生活中非常常見,比如迅雷就是我們常用的多線程的下載工具,當(dāng)然還有斷點續(xù)傳,斷點續(xù)傳我們在下一節(jié)來講,android手機端下載文件時也可以用多線程下載,我們這里是在j...
摘要:本次爬蟲項目將會用到模塊中的類,多線程豆瓣電影圖片??偨Y(jié)通過上述兩個爬蟲程序的對比,我們不難發(fā)現(xiàn),同樣是下載豆瓣電影,個網(wǎng)頁中的圖片,在沒有使用多線程的情況下,總共耗時約,而在使用多線程個線程的情況下,總共耗時約秒,效率整整提高了約倍。 爬蟲項目介紹 ??本次爬蟲項目將爬取豆瓣Top250電影的圖片,其網(wǎng)址為:https://movie.douban.com/top250, 具體頁面如...
摘要:批評的人通常都會說的多線程編程太困難了,眾所周知的全局解釋器鎖,或稱使得多個線程的代碼無法同時運行。多線程起步首先讓我們來創(chuàng)建一個名為的模塊。多進(jìn)程可能比多線程更易使用,但需要消耗更大的內(nèi)存。 批評 Python 的人通常都會說 Python 的多線程編程太困難了,眾所周知的全局解釋器鎖(Global Interpreter Lock,或稱 GIL)使得多個線程的 Python 代碼無...
閱讀 1673·2021-11-16 11:44
閱讀 2407·2021-10-11 11:07
閱讀 4073·2021-10-09 09:41
閱讀 677·2021-09-22 15:52
閱讀 3199·2021-09-09 09:33
閱讀 2715·2019-08-30 15:55
閱讀 2295·2019-08-30 15:55
閱讀 846·2019-08-30 15:55