使用多线程下载文件可以更快完成文件的下载,多线程下载文件之所以快,是因为其抢占的服务器资源多。如:假
设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计算机中并非并发执行,而
是由CPU划分时间片轮流执行,如果A应用使用了99条线程下载文件,那么相当于占用了99个用户的资源,假设
一秒内CPU分配给每条线程的平均执行时间是10ms,A应用在服务器中一秒内就得到了990ms的执行时间,而其
他应用在一秒内只有10ms的执行时间。就如同一个水龙头,每秒出水量相等的情况下,放990毫秒的水肯定比放
10毫秒的水要多。
代码实现:
package cn.mzba.download;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MulThreadDownloader {
/**
* 1、首先获取网络上的内容,然后获取文件的长度,标题。
* 然后在本地上生成一个同样大小并且同名的文件。
* 2、执行线程
* 3、线程首先定义一个随机输入流,用来下载文件同步写入本地文件
* 设置Range从指定的开始位置-结束位置下载文件。
* 4、获取服务器返回的输入流写入文件。
*
*/
public static void main(String[] args)throws Exception {
String path = "http://www.world3dmodel.com/bbs/attachments/month_1012/10121516044465687722ce156c.jpg";
new MulThreadDownloader().download(path,3);
System.in.read();
}
public void download(String path,int threadsize)throws Exception{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
int length = conn.getContentLength(); //获取文件长度
File localfile = new File(getFileName(path));
RandomAccessFile file = new RandomAccessFile(localfile, "rwd");
file.setLength(length);
file.close();
//计算每条线程下载的数据长度
int block = length % threadsize == 0 ? length / threadsize : length / threadsize + 1;
for(int i = 0;i < threadsize; i++){
new DownLoadThread(i,url,block,localfile).start();
}
}
private final class DownLoadThread extends Thread{
private int threadid;
private URL url;
private int block;
private File localfile;
public DownLoadThread(int threadid, URL url, int block, File localfile) {
this.threadid = threadid;
this.block = block;
this.url = url;
this.localfile = localfile;
}
@Override
public void run() {
int startposition = threadid * block; //从网络文件的什么位置开始下载数据
int endposition = startposition + block -1; //下载到文件的什么位置结束
RandomAccessFile file;
try {
file = new RandomAccessFile(localfile, "rwd");
file.seek(startposition);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
conn.setRequestProperty("Range", "bytes=" + startposition + "-" + endposition);
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1){
file.write(buffer,0,len);
}
is.close();
file.close();
System.out.println("线程id" + threadid + "已经下载完成");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.run();
}
}
public static String getFileName(String path){
return path.substring(path.lastIndexOf("/") + 1);
}
}