欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)多線程下載和斷點(diǎn)續(xù)傳

 更新時(shí)間:2022年06月24日 08:39:35   作者:談?wù)劦男那? 
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多線程下載和斷點(diǎn)續(xù)傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

java的多線程下載能夠明顯提升下載的速度,平時(shí)我們用的迅雷軟件之所以能夠下載那么快,就是使用了多線程;當(dāng)用戶在下載的過程中,有斷電或斷網(wǎng)的可能,當(dāng)用戶再次點(diǎn)擊下載時(shí),應(yīng)該讓用戶接著原來的進(jìn)度進(jìn)行下載,這可以節(jié)約用戶的流量,所以要用到斷點(diǎn)續(xù)傳的功能。下面是通過Java代碼實(shí)現(xiàn)多線程下載和斷點(diǎn)續(xù)傳的詳細(xì)代碼。

1、創(chuàng)建一個(gè)類,用于文件的下載

package com.edu.thread;
?
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
?
public class MultiDownload2 {
?? ?static String path = "http://localhost:8080/wlan.zip";
?? ?//開啟線程的數(shù)量
?? ?static int threadCount = 6;
?? ?//下載結(jié)束的線程數(shù)
?? ?static int threadFinished = 0;
?? ?public static void main(String[] args) {
?? ?try {
?? ??? ?URL url = new URL(path);
?? ??? ?HttpURLConnection conn = (HttpURLConnection) url.openConnection();
?? ??? ?conn.setRequestMethod("GET");
?? ??? ?conn.setConnectTimeout(5000);
?? ??? ?conn.setReadTimeout(5000);
?? ??? ?//此時(shí)只是確定和服務(wù)器建立了連接,但并沒有開始下載任務(wù)
?? ??? ?if (conn.getResponseCode()==200) {
?? ??? ??? ?//拿到文件的長度
?? ??? ??? ?int length = conn.getContentLength();
?? ??? ??? ?//指定文件路徑和文件名
?? ??? ??? ?File file = new File("d://文件測試", getFileName(path));
?? ??? ??? ?//創(chuàng)建隨機(jī)存儲文件大小,為了建立一個(gè)和源文件大小相同的存儲區(qū)間
?? ??? ??? ?RandomAccessFile raf = new RandomAccessFile(file, "rwd");
?? ??? ??? ?//設(shè)置臨時(shí)文件的大小,和服務(wù)器文件一模一樣
?? ??? ??? ?raf.setLength(length);
?? ??? ??? ?//計(jì)算每個(gè)線程下載的字節(jié)數(shù)
?? ??? ??? ?int size = length / threadCount;
?? ??? ??? ?//計(jì)算三個(gè)線程下載的開始位置和結(jié)束位置
?? ??? ??? ?for (int i = 0; i < threadCount; i++) {
?? ??? ??? ??? ?int startIndex = i * size;
?? ??? ??? ??? ?int endIndex = (i + 1) * size-1;
?? ??? ??? ??? ?//如果是最后一個(gè)線程,要把結(jié)尾讀完
?? ??? ??? ??? ?if (i == threadCount-1) {
?? ??? ??? ??? ??? ?//length從0開始讀,所以length-1表示最后一個(gè)字節(jié)
?? ??? ??? ??? ??? ?endIndex = length-1;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?//打印三個(gè)線程的開始與結(jié)束位置
?? ??? ??? ??? ?System.out.println("線程"+i+"的開始和結(jié)束位置:"+startIndex+"----"+endIndex);
?? ??? ??? ??? ?//開啟線程,傳入線程ID,下載的開始位置和下載的結(jié)束位置
?? ??? ??? ??? ?new DownloadThread(i, startIndex, endIndex).start();;
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?} catch (Exception e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
?? ?/*
?? ?* 獲取文件名
?? ?*/
?? ?public static String getFileName(String path){
?? ??? ?int index=path.lastIndexOf("/");
?? ??? ?return path.substring(index + 1);
?? ?}
}

2、創(chuàng)建另一個(gè)類,用于開啟子線程

package com.edu.thread;
?
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
//新開啟一個(gè)線程,用于完成下載任務(wù)
class DownloadThread extends Thread{
?
?? ?int thredId;
?? ?int startIndex;
?? ?int endIndex;
?? ?
?? ?public DownloadThread(int thredId, int startIndex, int endIndex) {
?? ??? ?super();
?? ??? ?this.thredId = thredId;
?? ??? ?this.startIndex = startIndex;
?? ??? ?this.endIndex = endIndex;
?? ?}
?? ?
?? ?public void run() {
?? ??? ?try {
?? ??? ?//下載進(jìn)度文件保存的路徑和文件名
?? ??? ?File progressFile = new File("d://文件測試",(thredId + ".txt"));
?? ??? ?//判斷保存下載進(jìn)度的臨時(shí)文件是否存在,以便確定下載的開始位置
?? ??? ?if (progressFile.exists()) {
?? ??? ??? ?FileInputStream fis = new FileInputStream(progressFile);
?? ??? ??? ?BufferedReader bReader = new BufferedReader(new InputStreamReader(fis));
?? ??? ??? ?//拿到臨時(shí)文件中保存的數(shù)據(jù),并把此數(shù)據(jù)設(shè)置為新的開始位置
?? ??? ??? ?int text = Integer.parseInt(bReader.readLine());
?? ??? ??? ?startIndex = text;
?? ??? ??? ?fis.close();
?? ??? ??? ?}
?? ??? ??? ?System.out.println("線程"+thredId+"的最終開始下載位置是:"+startIndex);
?? ??? ??? ?
?? ??? ??? ?URL url = new URL(MultiDownload2.path);
?? ??? ??? ?HttpURLConnection conn = (HttpURLConnection) url.openConnection();
?? ??? ??? ?conn.setRequestMethod("GET");
?? ??? ??? ?conn.setConnectTimeout(5000);
?? ??? ??? ?conn.setReadTimeout(5000);
?? ??? ??? ?//設(shè)置請求數(shù)據(jù)的范圍
?? ??? ??? ?conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
?? ??? ??? ?//建立連接,狀態(tài)碼206表示請求部分?jǐn)?shù)據(jù)成功,此時(shí)開始下載任務(wù)
?? ??? ??? ?if (conn.getResponseCode()==206) {
?? ??? ??? ??? ?InputStream is = conn.getInputStream();
?? ??? ??? ??? ?//指定文件名和文件路徑
?? ??? ??? ??? ?File file = new File(MultiDownload2.getFileName(MultiDownload2.path) );
?? ??? ??? ??? ?int len = 0;
?? ??? ??? ??? ?byte [] b = new byte[1024];
?? ??? ??? ??? ?//三個(gè)線程各自創(chuàng)建自己的隨機(jī)存儲文件
?? ??? ??? ??? ?RandomAccessFile raf = new RandomAccessFile(file, "rwd");
?? ??? ??? ??? ?//設(shè)置數(shù)據(jù)從哪個(gè)位置開始寫入數(shù)據(jù)到臨時(shí)文件
?? ??? ??? ??? ?raf.seek(startIndex);
?? ??? ??? ??? ?//設(shè)置當(dāng)前線程下載的總字節(jié)數(shù)
?? ??? ??? ??? ?int total = 0;
?? ??? ??? ??? ?long start = System.currentTimeMillis();
?? ??? ??? ??? ?
?? ??? ??? ??? ?//當(dāng)下載意外停止時(shí),記錄當(dāng)前下載進(jìn)度
?? ??? ??? ??? ?int currentPosition = startIndex;
?? ??? ??? ??? ?
?? ??? ??? ??? ?while ((len=is.read(b))!=-1) {
?? ??? ??? ??? ??? ?raf.write(b,0,len);
?? ??? ??? ??? ??? ?//打印當(dāng)前線程下載的總字節(jié)數(shù)
?? ??? ??? ??? ??? ?total += len;
?? ??? ??? ??? ??? ?/**
?? ??? ??? ??? ??? ?* 實(shí)現(xiàn)斷點(diǎn)續(xù)傳的功能
?? ??? ??? ??? ??? ?*/
?? ??? ??? ??? ??? ?//RandomAccessFile主要用來存放下載的臨時(shí)文件,可以用FileOutputStream代替
?? ??? ??? ??? ??? ?RandomAccessFile rafProgress = new RandomAccessFile(progressFile, "rwd");
?? ??? ??? ??? ??? ?//再次下載時(shí)的開始位置
?? ??? ??? ??? ??? ?currentPosition = startIndex + total;
?? ??? ??? ??? ??? ?//把下載進(jìn)度寫進(jìn)rafProgress臨時(shí)文件,下一次下載時(shí),就以這個(gè)值作為新的startIndex
?? ??? ??? ??? ??? ?rafProgress.write((currentPosition + "").getBytes());
?? ??? ??? ??? ??? ?//關(guān)流
?? ??? ??? ??? ??? ?rafProgress.close();
?? ??? ??? ??? ??? ?System.out.println("線程"+thredId+"已經(jīng)下載了"+total);
?? ??? ??? ??? ?}
?? ??? ??? ??? ?raf.close();
?? ??? ??? ??? ?long end = System.currentTimeMillis();
?? ??? ??? ??? ?//打印線程下載文件用時(shí)
?? ??? ??? ??? ?System.out.println("線程"+thredId+"下載文件用時(shí)"+(end-start)+"ms");
?? ??? ??? ??? ?//打印線程的結(jié)束
?? ??? ??? ??? ?System.out.println("線程:"+thredId+" 下載結(jié)束了 !!!");
?? ??? ??? ??? ?//下載結(jié)束后,刪除所有的臨時(shí)文件
?? ??? ??? ??? ?MultiDownload2.threadFinished ++;
?? ??? ??? ??? ?//使用同步語句塊,保證線程的安全性
?? ??? ??? ??? ?synchronized (MultiDownload2.path) {
?? ??? ??? ??? ?//如果這個(gè)條件成立,說明所有的線程下載結(jié)束
?? ??? ??? ??? ?if (MultiDownload2.threadFinished == MultiDownload2.threadCount) {
?? ??? ??? ??? ??? ?for (int i = 0; i < MultiDownload2.threadCount; i++) {
?? ??? ??? ??? ??? ??? ?//刪除三個(gè)線程產(chǎn)生的臨時(shí)文件
?? ??? ??? ??? ??? ??? ?File temp = new File("d://文件測試", i + ".txt");
?? ??? ??? ??? ??? ??? ?temp.delete();
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?//保證三個(gè)線程的臨時(shí)文件同時(shí)被刪除
?? ??? ??? ??? ??? ?MultiDownload2.threadFinished = 0;
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?} catch (Exception e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring?Boot中的max-http-header-size配置方式

    Spring?Boot中的max-http-header-size配置方式

    這篇文章主要介紹了Spring?Boot中的max-http-header-size配置方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier使用探索

    Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier使用探索

    這篇文章主要介紹了Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2024-01-01
  • java開發(fā)微服務(wù)架構(gòu)設(shè)計(jì)消息隊(duì)列的水有多深

    java開發(fā)微服務(wù)架構(gòu)設(shè)計(jì)消息隊(duì)列的水有多深

    今天我們說說消息隊(duì)列的問題,來帶大家探一探消息隊(duì)列的水有多深,希望看完本文大家在引入消息隊(duì)列的時(shí)候先想一想,是不是一定要引入?引入消息隊(duì)列后產(chǎn)生的問題能不能解決
    2021-10-10
  • Java中的Comparable和Comparator接口

    Java中的Comparable和Comparator接口

    這篇文章主要介紹了Java中的Comparable和Comparator接口,文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • Java實(shí)現(xiàn)線程的暫停和恢復(fù)的示例詳解

    Java實(shí)現(xiàn)線程的暫停和恢復(fù)的示例詳解

    這幾天的項(xiàng)目中,客戶給了個(gè)需求,希望我可以開啟一個(gè)任務(wù),想什么時(shí)候暫停就什么時(shí)候暫停,想什么時(shí)候開始就什么時(shí)候開始,所以本文小編給大家介紹了Java實(shí)現(xiàn)線程的暫停和恢復(fù)的示例,需要的朋友可以參考下
    2023-11-11
  • Java?hutool?List集合對象拷貝示例代碼

    Java?hutool?List集合對象拷貝示例代碼

    這篇文章主要介紹了Java?hutool?List集合對象拷貝的相關(guān)資料,文章還分享了在實(shí)現(xiàn)過程中遇到的一些問題,并強(qiáng)調(diào)了閱讀源碼和正確配置CopyOptions的重要性,需要的朋友可以參考下
    2024-12-12
  • Java BigDecimal解決double精度丟失的問題

    Java BigDecimal解決double精度丟失的問題

    我們在日常開發(fā)中, 有很多時(shí)候會遇到小數(shù)(double類型)精確計(jì)算,本文主要介紹了Java BigDecimal解決double精度丟失的問題,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Java中自動生成構(gòu)造方法詳解

    Java中自動生成構(gòu)造方法詳解

    這篇文章主要介紹了Java中自動生成構(gòu)造方法詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java多線程的用法詳解

    Java多線程的用法詳解

    本篇文章介紹了,在Java中多線程的用法詳解。需要的朋友參考下
    2013-04-04
  • Java 反射機(jī)制原理與用法詳解

    Java 反射機(jī)制原理與用法詳解

    這篇文章主要介紹了Java 反射機(jī)制原理與用法,結(jié)合實(shí)例形式詳細(xì)分析了java反射機(jī)制的相關(guān)概念、原理、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-12-12

最新評論