最近学习了线程这一块,发现很有意思,就把自己写的代码保存下来为了更好的学习与交流
多线程下载注意的关键:
1:先明白多线程下载的原理,明白原理后,实现代码已经理解代码就不难。
2:如何确定下载文件的总大小
3:根据文件总大小和线程数量,来确定每个线程下载的起始位置和结束位置,以及最后一个线程他负责大小的特殊性。
4:执行线程下载的时候,要设置本次http请求所请求的数据的区间,也就是开始位置和结束为止。响应码返回值是206而不是200.
connection.setRequestProperty(“Range”, “bytes=” + startIndex + “-” + endIndex);
/************************************************************************************/
package com.cnu.multithreaddownload;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class MultiThreadDownload {
static int ThreadCount = 3;
// 确定下载地址,这是本地Tomcat上一个地址
static String path = “http://10.1.156.35:8080/adsafese.v1.1.1.9900.exe“;
public static void main(String[] args) {
// 发送get请求,请求这个地址的资源.第一次发送get请求,是为了得到文件的长度,而不是下载
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
if (connection.getResponseCode() == 200) {
// 拿到所请求资源文件的长度
int length = connection.getContentLength();
File file = new File("adsafese.v1.1.1.9900.exe"); //默认会在项目根路径上
// 生成临时文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
// 设置临时文件的大小
raf.setLength(length);
raf.close();
// 计算出每个线程应该下载多少个字节
int size = length / ThreadCount;
for (int i = 0; i < ThreadCount; i++) {
// 计算线程下载的开始位置和结束位置
int startIndex = i * size;
int endIndex = (i + 1) * size - 1;
if (i == (ThreadCount - 1)) {
endIndex = length - 1;
}
System.out.println("线程" + i + "的下载区间是:" + startIndex
+ "-----" + endIndex);
new DownloadThread(startIndex, endIndex, i).start();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class DownloadThread extends Thread {
int startIndex;
int endIndex;
int threadId;
public DownloadThread(int startIndex, int endIndex, int threadId) {
super();
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
// 再次发送http请求,下载源文件
URL url;
try {
url = new URL(MultiThreadDownload.path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
//设置本次http请求所请求的数据的区间
connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//请求部分数据,响应码是206
if (connection.getResponseCode() == 206) {
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len = 0;
int total = 0;
//拿到临时文件的输入流
File file = new File("adsafese.v1.1.1.9900.exe");
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//把文件的写入位置移动至startIndex
raf.seek(startIndex);
while ((len = is.read(b)) != -1) {
//每次读取流里数据之后,同步把数据写入临时文件中
raf.write(b, 0, len);
total += len;
System.out.println("线程" + threadId + "下载了" + total );
}
System.out.println("线程" + threadId + "下载完毕--------------------------------------------------------------------" );
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}