使用多线程下载文件可以更快完成文件的下载,多线程下载文件之所以快,是因为其抢占的服务器资源多。
1、得到下载文件的长度,然后设置本地文件的长度;
int length = connection.getContentLength();
2、根据文件长度和线程数计算每条线程下载的数据长度和下载位 置;
//假设三个线程下载资源
//平均每一个线程下载的文件的大小
int
blockSize = length/ThreadCount;
for (int
threadId = 1; threadId <= ThreadCount; threadId++) {
//每一个线程下载的开始和结束位置
int
startIndex = (threadId - 1)*blockSize;
int endIndex
= threadId*blockSize - 1;
//最后一个线程下载的长度长点
if (threadId
== ThreadCount) {
endIndex =
length;
}
3、使用Http的Range头字段指定每条线程从本地文件的什么位置开始写入数据。
connection.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
完整代码:
public class Demo {
//声明线程数
private
static int ThreadCount = 3;
public
static void main(String[] args) {
Demo demo =
new Demo();
demo.Download();
}
private void
Download(){
String path
= "http://localhost:8080/QQ.exe";
URL
url;
try {
url = new
URL(path);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
int code =
connection.getResponseCode();
if (code ==
200) {
//服务器返回的文件长度 其实就是文件的大小
int length =
connection.getContentLength();
System.out.println("文件的长度:"+length);
//在本地创建一个和服务器一样大小的临时文件
RandomAccessFile raf = new RandomAccessFile("QQ1.exe",
"rwd");
raf.setLength(length);
//假设三个线程下载资源
//平均每一个线程下载的文件的大小
int
blockSize = length/ThreadCount;
for (int
threadId = 1; threadId <= ThreadCount; threadId++) {
//每一个线程下载的开始和结束位置
int
startIndex = (threadId - 1)*blockSize;
int endIndex
= threadId*blockSize - 1;
//最后一个线程下载的长度长点
if (threadId
== ThreadCount) {
endIndex =
length;
}
System.out.println("每个线程下载的起止位置:"+threadId+":"+startIndex+"------->"+endIndex);
new
DownloadThread(startIndex, endIndex, threadId, path).start();
}
}else
{
System.out.println("服务器错误");
}
} catch
(Exception e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
}
public
static class DownloadThread extends Thread{
private int
startIndex;
private int
endIndex;
private int
threadId;
private
String path;
public
DownloadThread(int startIndex, int endIndex, int threadId,
String path)
{
super();
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
this.path =
path;
}
public void
run() {
try {
URL url =
new URL(path);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setRequestMethod("GET");
//请求服务器下载部分的文件 指定文件的大小
connection.setRequestProperty("Range",
"bytes="+startIndex+"-"+endIndex);
connection.setReadTimeout(5000);
int code =
connection.getResponseCode();
System.out.println("code:"+code);
//返回全部的资源,由于定义了大小,返回的是当前位置文件对应的输入流
InputStream
inputStream = connection.getInputStream();
RandomAccessFile raf = new RandomAccessFile("QQ1.exe",
"rwd");
raf.seek(startIndex);
int len =
0;
byte[] buf =
new byte[1024];
while ((len
= inputStream.read(buf)) != -1){
raf.write(buf, 0, len);
}
inputStream.close();
raf.close();
System.out.println("线程:"+threadId+"下载完毕。。。。。");
} catch
(IOException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
}
}
}
先来看一下多线程传输实现原理:
将源文件按长度为分为N块文件,然后开辟N个线程,每个线程传输一块,最后合并所有线线程文件.比如一个文件50M我们按长度可以分5个线程传输.第一线程从0-10M,第二线程从10M-20M......最后合并5个线程文件. 多线程下载的实现过程:1、得到下载文件的长度,然后设置本地文件的长度;
int length = connection.getContentLength();
2、根据文件长度和线程数计算每条线程下载的数据长度和下载位 置;
3、使用Http的Range头字段指定每条线程从本地文件的什么位置开始写入数据。
connection.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
完整代码:
public class Demo {
}