一:需求分析
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