Java多線程實現下載功能

來源:互聯網
上載者:User

網上找了份資料,是別人完成的Java實現多線程下載的功能。

Java多線程的好處挺多的,可以充分利用CPU的資源,簡化編程模型,簡化非同步事件的處理,使GUI更有效率,節約成本。

下面是實現多線程下載的代碼:

package com.zyujie.util;import java.io.InputStream;import java.io.RandomAccessFile;public class DownThread extends Thread {// 定義位元組數組(取水的竹筒)的長度private final int BUFF_LEN = 32;// 定義下載的起始點private long start;// 定義下載的結束點private long end;// 下載資源對應的輸入資料流private InputStream is;// 將下載到的位元組輸出到raf中private RandomAccessFile raf;// 構造器,傳入輸入資料流,輸出資料流和下載起始點、結束點public DownThread(long start, long end, InputStream is, RandomAccessFile raf) {// 輸出該線程負責下載的位元組位置System.out.println(start + "---->" + end);this.start = start;this.end = end;this.is = is;this.raf = raf;}public void run() {try {is.skip(start);raf.seek(start);// 定義讀取輸入資料流內容的的緩衝數組(竹筒)byte[] buff = new byte[BUFF_LEN];// 本線程負責下載資源的大小long contentLen = end - start;// 定義最多需要讀取幾次就可以完成本線程的下載long times = contentLen / BUFF_LEN + 4;// 實際讀取的位元組數int hasRead = 0;for (int i = 0; i < times; i++) {hasRead = is.read(buff);// 如果讀取的位元組數小於0,則退出迴圈!if (hasRead < 0) {break;}raf.write(buff, 0, hasRead);}} catch (Exception ex) {ex.printStackTrace();}// 使用finally塊來關閉當前線程的輸入資料流、輸出資料流finally {try {if (is != null) {is.close();}if (raf != null) {raf.close();}} catch (Exception ex) {ex.printStackTrace();}}}}

 

package com.zyujie.util;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.URL;import java.net.URLConnection;public class MutilDown {public static void main(String[] args) {//定義幾個線程去下載final int DOWN_THREAD_NUM = 4;final String OUT_FILE_NAME = "down.jpg";InputStream[] isArr = new InputStream[DOWN_THREAD_NUM];RandomAccessFile[] outArr = new RandomAccessFile[DOWN_THREAD_NUM];try {// 建立一個URL對象URL url = new URL("http://hiphotos.baidu.com/240728057/pic/item/6a50e38242aad8f60cf4d2b3.jpg");// 以此URL對象開啟第一個輸入資料流isArr[0] = url.openStream();long fileLen = getFileLength(url);System.out.println("網路資源的大小" + fileLen);// 以輸出檔案名建立第一個RandomAccessFile輸出資料流//建立從中讀取和向其中寫入(可選)的隨機存取檔案流,第一個參數:檔案名稱,第二個參數是:參數指定用以開啟檔案的訪問模式//"rw"可能是可讀可寫,outArr[0] = new RandomAccessFile(OUT_FILE_NAME, "rw");// 建立一個與下載資源相同大小的空檔案for (int i = 0; i < fileLen; i++) {outArr[0].write(0);}// 每線程應該下載的位元組數long numPerThred = fileLen / DOWN_THREAD_NUM;// 整個下載資源整除後剩下的餘數模數long left = fileLen % DOWN_THREAD_NUM;for (int i = 0; i < DOWN_THREAD_NUM; i++) {// 為每個線程開啟一個輸入資料流、一個RandomAccessFile對象,// 讓每個線程分別負責下載資源的不同部分。//isArr[0]和outArr[0]已經使用,從不為0開始if (i != 0) {// 以URL開啟多個輸入資料流isArr[i] = url.openStream();// 以指定輸出檔案建立多個RandomAccessFile對象outArr[i] = new RandomAccessFile(OUT_FILE_NAME, "rw");}// 分別啟動多個線程來下載網路資源if (i == DOWN_THREAD_NUM - 1) {// 最後一個線程下載指定numPerThred+left個位元組new DownThread(i * numPerThred, (i + 1) * numPerThred+ left, isArr[i], outArr[i]).start();} else {// 每個線程負責下載一定的numPerThred個位元組new DownThread(i * numPerThred, (i + 1) * numPerThred,isArr[i], outArr[i]).start();}}} catch (Exception ex) {ex.printStackTrace();}}// 定義擷取指定網路資源的長度的方法public static long getFileLength(URL url) throws Exception {long length = 0;// 開啟該URL對應的URLConnectionURLConnection con = url.openConnection();// 擷取串連URL資源的長度long size = con.getContentLength();length = size;return length;}}

如果要實現斷點下載,則還需要額外增加一個設定檔(其實,一般的所有斷點下載工具都會在下載開始產生兩個檔案:一個是與網路資源大小相同的空檔案,一個是設定檔),該設定檔分別記錄每個線程已經下載到了哪個位元組,當網路斷開後再次下載時,每個線程根據設定檔裡記錄的位置向後下載即可

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.