多線程實現下載文件


一:需求分析

1:下載遠程資源文件,通過多線程下載,達到高效的目的。

2:使用5個線程分別下載文件的不同部分。

 

二:定義成員變量以及初始化變量

 1 // 定義成員變量
 2     private String path; // 遠程資源路徑
 3     private String targetPath; // 本地存儲路徑
 4     private DownFileThread[] threads; // 線程list
 5     private int threadNum; // 線程數量
 6     private long length; // 下載的文件大小
 7 
 8     // 構造初始化
 9     public DownloadUtil(String path, String targetPath, int threadNum) {
10         super();
11         this.path = path;
12         this.targetPath = targetPath;
13         this.threads = new DownFileThread[threadNum];
14         this.threadNum = threadNum;
15     }

 

三:多線程下載文件

 

 1 // 多線程下載文件資源
 2     public void download() {
 3         URL url;
 4         try {
 5             url = new URL(path);
 6             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 7             conn.setReadTimeout(5 * 1000); // 設置超時時間為5秒
 8             conn.setRequestMethod("GET");
 9             conn.setRequestProperty("connection", "keep-alive");
10             conn.setRequestProperty("accept", "*/*");
11 
12             // 獲取遠程文件的大小
13             length = conn.getContentLength();
14             conn.disconnect();
15 
16             // 設置本地文件大小
17             RandomAccessFile targetFile = new RandomAccessFile(targetPath, "rw");
18             targetFile.setLength(length);
19 
20             // 每個線程下載大小
21             long avgPart = length / threadNum + 1;
22             // 下載文件
23             for (int i = 0; i < threadNum; i++) {
24                 long startPos = avgPart * i;
25                 RandomAccessFile targetTmp = new RandomAccessFile(targetPath,
26                         "rw");
27                 targetTmp.seek(startPos); // 分段下載
28                 threads[i] = new DownFileThread(startPos, targetTmp, avgPart);
29                 threads[i].start();
30             }
31         } catch (Exception e) {
32             e.printStackTrace();
33         }
34     }

啟動多個線程,每個線程下載文件的一部分,並發執行。

 

四:監控文件下載進度

1 // 監控下載進度
2     public double getDownRate() {
3         int currentSize = 0;
4         for (int i = 0; i < threadNum; i++) {
5             currentSize += threads[i].length;
6         }
7         return currentSize * 1.0 / length;
8     }

如果下載的文件比較大,可以使用進度條顯示。

 

五:定義線程類

 

 1 // 定義線程類
 2     class DownFileThread extends Thread {
 3         private long startPos;
 4         private RandomAccessFile raf;
 5         private long size;
 6         private long length;
 7 
 8         public DownFileThread(long startPos, RandomAccessFile raf, long size) {
 9             super();
10             this.startPos = startPos;
11             this.raf = raf;
12             this.size = size;
13         }
14 
15         public void run() {
16             URL url;
17             try {
18                 url = new URL(path);
19                 HttpURLConnection conn = (HttpURLConnection) url
20                         .openConnection();
21                 conn.setReadTimeout(5 * 1000); // 設置超時時間為5秒
22                 conn.setRequestMethod("GET");
23                 conn.setRequestProperty("connection", "keep-alive");
24                 conn.setRequestProperty("accept", "*/*");
25 
26                 InputStream in = conn.getInputStream();
27                 in.skip(this.startPos);
28                 byte[] buf = new byte[1024];
29                 int hasRead = 0;
30                 while (length < size && (hasRead = in.read(buf)) != -1) {
31                     raf.write(buf, 0, hasRead);
32                     length += hasRead;
33                 }
34                 raf.close();
35                 in.close();
36             } catch (Exception e) {
37                 e.printStackTrace();
38             }
39         }
40     }

 

六:測試多線程下載文件

 1 public static void main(String[] args) {
 2         String path = "http://localhost:8080/healthcare/html/HealthCare.war";
 3         String targetPath = "D:/healthcare.war";
 4         final DownloadUtil download = new DownloadUtil(path, targetPath, 4);
 5         download.download();
 6         // 主線程負責下載文件,在啟動一個線程負責監控下載的進度
 7         new Thread(new Runnable() {
 8 
 9             @Override
10             public void run() {
11                 while (download.getDownRate() < 1) {
12                     System.out.println(download.getDownRate());
13                     try {
14                         Thread.sleep(200); // 200毫秒掃描一次
15                     } catch (InterruptedException e) {
16                         e.printStackTrace();
17                     }
18                 }
19             }
20 
21         }).start();
22     }

 

七:全部代碼如下

  1 /**
  2  * 
  3  */
  4 package com.hlcui.thread;
  5 
  6 import java.io.InputStream;
  7 import java.io.RandomAccessFile;
  8 import java.net.HttpURLConnection;
  9 import java.net.URL;
 10 
 11 /**
 12  * @author Administrator 多線程下載文件
 13  */
 14 public class DownloadUtil {
 15     // 定義成員變量
 16     private String path; // 遠程資源路徑
 17     private String targetPath; // 本地存儲路徑
 18     private DownFileThread[] threads; // 線程list
 19     private int threadNum; // 線程數量
 20     private long length; // 下載的文件大小
 21 
 22     // 構造初始化
 23     public DownloadUtil(String path, String targetPath, int threadNum) {
 24         super();
 25         this.path = path;
 26         this.targetPath = targetPath;
 27         this.threads = new DownFileThread[threadNum];
 28         this.threadNum = threadNum;
 29     }
 30 
 31     // 多線程下載文件資源
 32     public void download() {
 33         URL url;
 34         try {
 35             url = new URL(path);
 36             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 37             conn.setReadTimeout(5 * 1000); // 設置超時時間為5秒
 38             conn.setRequestMethod("GET");
 39             conn.setRequestProperty("connection", "keep-alive");
 40             conn.setRequestProperty("accept", "*/*");
 41 
 42             // 獲取遠程文件的大小
 43             length = conn.getContentLength();
 44             conn.disconnect();
 45 
 46             // 設置本地文件大小
 47             RandomAccessFile targetFile = new RandomAccessFile(targetPath, "rw");
 48             targetFile.setLength(length);
 49 
 50             // 每個線程下載大小
 51             long avgPart = length / threadNum + 1;
 52             // 下載文件
 53             for (int i = 0; i < threadNum; i++) {
 54                 long startPos = avgPart * i;
 55                 RandomAccessFile targetTmp = new RandomAccessFile(targetPath,
 56                         "rw");
 57                 targetTmp.seek(startPos); // 分段下載
 58                 threads[i] = new DownFileThread(startPos, targetTmp, avgPart);
 59                 threads[i].start();
 60             }
 61         } catch (Exception e) {
 62             e.printStackTrace();
 63         }
 64     }
 65 
 66     // 監控下載進度
 67     public double getDownRate() {
 68         int currentSize = 0;
 69         for (int i = 0; i < threadNum; i++) {
 70             currentSize += threads[i].length;
 71         }
 72         return currentSize * 1.0 / length;
 73     }
 74 
 75     // 定義線程類
 76     class DownFileThread extends Thread {
 77         private long startPos;
 78         private RandomAccessFile raf;
 79         private long size;
 80         private long length;
 81 
 82         public DownFileThread(long startPos, RandomAccessFile raf, long size) {
 83             super();
 84             this.startPos = startPos;
 85             this.raf = raf;
 86             this.size = size;
 87         }
 88 
 89         public void run() {
 90             URL url;
 91             try {
 92                 url = new URL(path);
 93                 HttpURLConnection conn = (HttpURLConnection) url
 94                         .openConnection();
 95                 conn.setReadTimeout(5 * 1000); // 設置超時時間為5秒
 96                 conn.setRequestMethod("GET");
 97                 conn.setRequestProperty("connection", "keep-alive");
 98                 conn.setRequestProperty("accept", "*/*");
 99 
100                 InputStream in = conn.getInputStream();
101                 in.skip(this.startPos);
102                 byte[] buf = new byte[1024];
103                 int hasRead = 0;
104                 while (length < size && (hasRead = in.read(buf)) != -1) {
105                     raf.write(buf, 0, hasRead);
106                     length += hasRead;
107                 }
108                 raf.close();
109                 in.close();
110             } catch (Exception e) {
111                 e.printStackTrace();
112             }
113         }
114     }
115 
116     // 測試
117     public static void main(String[] args) {
118         String path = "http://localhost:8080/healthcare/html/HealthCare.war";
119         String targetPath = "D:/healthcare.war";
120         final DownloadUtil download = new DownloadUtil(path, targetPath, 4);
121         download.download();
122         // 主線程負責下載文件,在啟動一個線程負責監控下載的進度
123         new Thread(new Runnable() {
124 
125             @Override
126             public void run() {
127                 while (download.getDownRate() < 1) {
128                     System.out.println(download.getDownRate());
129                     try {
130                         Thread.sleep(200); // 200毫秒掃描一次
131                     } catch (InterruptedException e) {
132                         e.printStackTrace();
133                     }
134                 }
135             }
136 
137         }).start();
138     }
139 }
View Code

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM