摘要:原理多線程下載的原理就是將要下載的文件分成若干份,其中每份都使用一個多帶帶的線程進行下載,這樣對于文件的下載速度自然就提高了許多。總結多線程的關鍵就是分配好需要下載的進程,定位進程下載的準確位置,獲取輸入流讀取數據,同時寫入到文件的相應位置。
原理
多線程下載的原理就是將要下載的文件分成若干份,其中每份都使用一個多帶帶的線程進行下載,這樣對于文件的下載速度自然就提高了許多。
既然要分成若干部分分工下載,自然要知道各個線程自己要下載的起始位置,與要下載的大小。所以我們要解決線程的分配與各個線程定位到下載的位置。
封裝對于多線程下載我們可以將其封裝到一個工具類中DownUtil,向其中傳入下載的鏈接、文件存儲路徑、需要下載的線程數
public DownUtil(String path, String targetFile, int threadNum) { this.path = path; this.targetFile = targetFile; this.threadNum = threadNum; downThreads = new DownThread[threadNum]; }
其中DownThread實現的是各個線程的下載
分配線程這里通過HttpURLConnection進行網絡請求下載,通過getContentLength()方法獲取下載文件的總大小,再對其平均分配各個線程需要下載的大小。這樣就確定了下載的大小,下面就是定位到各個線程的開始位置進行下載,這里可以使用RandomAccessFile來追蹤定位到要下載的位置,它的seek()方法可以進行定位。下面是詳細代碼:
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"); //設置本地文件大小 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,上面已經得到了各個線程要下載的初始位置,所以可以通過獲取網絡請求的輸入流InputStream,通過skip()方法跳躍到指定位置進行讀取數據,再寫入到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(); } } }
這樣就完成了一個簡單的多線程的下載,最后調用封裝類DownUtil就可以進行多線程下載。
總結多線程的關鍵就是分配好需要下載的進程,定位進程下載的準確位置,獲取輸入流讀取數據,同時寫入到文件的相應位置。可以借助RandomAccessFile來進行定位。
當然也并非開的線程數越多下載的速度也就越快,因為線程越多對于程序處理這些線程也是一種負擔,過多的話反而會降低下載的速度,所以要合理運用。
個人blog地址:https://idisfkj.github.io/arc...
關注文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64854.html
摘要:多線程下載原理及步驟在本地創建一個大小跟服務器文件相同大小的臨時文件。在這里在介紹一個有關多線程下載的中的相關類隨機文件訪問類只有才有搜尋方法,而這個方法也只適用于文件。利用這個類才能實現文件的多線程下載。 多線程下載在我們生活中非常常見,比如迅雷就是我們常用的多線程的下載工具,當然還有斷點續傳,斷點續傳我們在下一節來講,android手機端下載文件時也可以用多線程下載,我們這里是在j...
摘要:本次爬蟲項目將會用到模塊中的類,多線程豆瓣電影圖片。總結通過上述兩個爬蟲程序的對比,我們不難發現,同樣是下載豆瓣電影,個網頁中的圖片,在沒有使用多線程的情況下,總共耗時約,而在使用多線程個線程的情況下,總共耗時約秒,效率整整提高了約倍。 爬蟲項目介紹 ??本次爬蟲項目將爬取豆瓣Top250電影的圖片,其網址為:https://movie.douban.com/top250, 具體頁面如...
摘要:批評的人通常都會說的多線程編程太困難了,眾所周知的全局解釋器鎖,或稱使得多個線程的代碼無法同時運行。多線程起步首先讓我們來創建一個名為的模塊。多進程可能比多線程更易使用,但需要消耗更大的內存。 批評 Python 的人通常都會說 Python 的多線程編程太困難了,眾所周知的全局解釋器鎖(Global Interpreter Lock,或稱 GIL)使得多個線程的 Python 代碼無...
閱讀 1649·2021-11-16 11:44
閱讀 2393·2021-10-11 11:07
閱讀 4036·2021-10-09 09:41
閱讀 663·2021-09-22 15:52
閱讀 3187·2021-09-09 09:33
閱讀 2701·2019-08-30 15:55
閱讀 2284·2019-08-30 15:55
閱讀 837·2019-08-30 15:55