摘要:多線程下載原理及步驟在本地創(chuàng)建一個大小跟服務(wù)器文件相同大小的臨時文件。在這里在介紹一個有關(guān)多線程下載的中的相關(guān)類隨機(jī)文件訪問類只有才有搜尋方法,而這個方法也只適用于文件。利用這個類才能實(shí)現(xiàn)文件的多線程下載。
多線程下載在我們生活中非常常見,比如迅雷就是我們常用的多線程的下載工具,當(dāng)然還有斷點(diǎn)續(xù)傳,斷點(diǎn)續(xù)傳我們在下一節(jié)來講,android手機(jī)端下載文件時也可以用多線程下載,我們這里是在java中寫一個測試,其實(shí)android中的實(shí)現(xiàn)和java是一樣的,學(xué)會了java就知道怎么在android中實(shí)現(xiàn)了,廢話不多說了,怎么實(shí)現(xiàn)多線程和多線程的原理是什么樣的,現(xiàn)在我們來學(xué)習(xí)一下。
在本地創(chuàng)建一個大小跟服務(wù)器文件相同大小的臨時文件。
計(jì)算分配幾個線程去下載服務(wù)器上的資源,知道每個線程下載文件的位置。
文件的長度/3(線程的個數(shù))=每個線程下載文件的大小
假設(shè)文件長度為10,則
線程1:0-2
線程2:3-5
線程3:6-文件末尾
每個線程下載的位置的計(jì)算方式:
開始位置:
(線程id - 1)* 每一塊的大小
結(jié)束位置:
(線程id * 每一塊大?。?1
開啟多(3)個線程,每一個線程下載對應(yīng)位置的文件
如果所有的線程都把自己的數(shù)據(jù)下載完畢了,服務(wù)器上的資源就被下載到本地了。
在這里在介紹一個有關(guān)多線程下載的java中的相關(guān)類RandomAccessFile
RandomAccessFile 隨機(jī)文件訪問類
只有RandomAccessFile才有seek搜尋方法,而這個方法也只適用于文件。通過seek()方法指定位置,定位文件,即可以指定隨機(jī)寫文件的時候從哪個位置開始寫。利用這個類才能實(shí)現(xiàn)文件的多線程下載。
基本原理和相關(guān)介紹如上,就這些,現(xiàn)在我們看看代碼:
package net.loonggg.test; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; /*** * 多線程下載 * * @author loonggg * */ public class MutilDownloader { // 開啟的線程的個數(shù) public static final int THREAD_COUNT = 3; public static void main(String[] args) throws Exception { String path = "http://down.360safe.com/yunpan/360wangpan_setup.exe"; // 連接服務(wù)器,獲取一個文件,獲取文件的長度,在本地創(chuàng)建一個大小跟服務(wù)器文件大小一樣的臨時文件 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 設(shè)置網(wǎng)絡(luò)請求超時時間 conn.setConnectTimeout(5000); // 設(shè)置請求方式 conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { // 服務(wù)器返回的數(shù)據(jù)的長度,實(shí)際就是文件的長度 int length = conn.getContentLength(); System.out.println("----文件總長度----" + length); // 在客戶端本地創(chuàng)建出來一個大小跟服務(wù)器端文件一樣大小的臨時文件 RandomAccessFile raf = new RandomAccessFile("yunpan.exe", "rwd"); // 指定創(chuàng)建的這個文件的長度 raf.setLength(length); // 關(guān)閉raf raf.close(); // 假設(shè)是3個線程去下載資源 // 平均每一個線程下載的文件的大小 int blockSize = length / THREAD_COUNT; for (int threadId = 1; threadId <= THREAD_COUNT; threadId++) { // 計(jì)算每個線程下載的開始位置和結(jié)束位置 int startIndex = (threadId - 1) * blockSize; int endIndex = threadId * blockSize - 1; if (threadId == THREAD_COUNT) { endIndex = length; } System.out.println("----threadId---" + threadId + "--startIndex--" + startIndex + "--endIndex--" + endIndex); // 開啟每一個線程 new DownloadThread(path, threadId, startIndex, endIndex) .start(); } } } /** * 下載文件的子線程,每一個線程下載對應(yīng)位置的文件 * * @author loonggg * */ public static class DownloadThread extends Thread { private int threadId; private int startIndex; private int endIndex; private String path; /** * @param path * 下載文件在服務(wù)器上的路徑 * @param threadId * 線程id * @param startIndex * 線程下載的開始位置 * @param endIndex * 線程下載的結(jié)束位置 */ public DownloadThread(String path, int threadId, int startIndex, int endIndex) { this.path = path; this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); // 重要:請求服務(wù)器下載部分的文件 指定文件的位置 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); conn.setConnectTimeout(5000); // 從服務(wù)器請求全部資源的狀態(tài)碼200 ok 如果從服務(wù)器請求部分資源的狀態(tài)碼206 ok int code = conn.getResponseCode(); System.out.println("---code---" + code); InputStream is = conn.getInputStream();// 已經(jīng)設(shè)置了請求的位置,返回的是當(dāng)前位置對應(yīng)的文件的輸入流 RandomAccessFile raf = new RandomAccessFile("yunpan.exe", "rwd"); // 隨機(jī)寫文件的時候從哪個位置開始寫 raf.seek(startIndex);// 定位文件 int len = 0; byte[] buffer = new byte[1024]; while ((len = is.read(buffer)) != -1) { raf.write(buffer, 0, len); } is.close(); raf.close(); System.out.println("線程" + threadId + ":下載完畢了!"); } catch (Exception e) { e.printStackTrace(); } } } }
公眾號:非著名程序員(smart_android) 歡迎大家關(guān)注,每天一篇原創(chuàng)技術(shù)文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/65931.html
摘要:大多數(shù)待遇豐厚的開發(fā)職位都要求開發(fā)者精通多線程技術(shù)并且有豐富的程序開發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問題在面試中經(jīng)常會被提到。將對象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對象稱之為反序列化。 JVM 內(nèi)存溢出實(shí)例 - 實(shí)戰(zhàn) JVM(二) 介紹 JVM 內(nèi)存溢出產(chǎn)生情況分析 Java - 注解詳解 詳細(xì)介紹 Java 注解的使用,有利于學(xué)習(xí)編譯時注解 Java 程序員快速上手 Kot...
摘要:本文將分享軟件基本用法及文件進(jìn)程注冊表查看,這是一款微軟推薦的系統(tǒng)監(jiān)視工具,功能非常強(qiáng)大可用來檢測惡意軟件??梢詭椭褂谜邔ο到y(tǒng)中的任何文件注冊表操作進(jìn)行監(jiān)視和記錄,通過注冊表和文件讀寫的變化,有效幫助診斷系統(tǒng)故障或發(fā)現(xiàn)惡意軟件病毒及木馬。 ...
閱讀 4116·2023-04-26 02:07
閱讀 3742·2021-10-27 14:14
閱讀 2966·2021-10-14 09:49
閱讀 1686·2019-08-30 15:43
閱讀 2696·2019-08-29 18:33
閱讀 2432·2019-08-29 17:01
閱讀 976·2019-08-29 15:11
閱讀 678·2019-08-29 11:06