转载自:http://blog.csdn.net/imstephen/article/details/10816285
使用多线程下载文件可以更快地完成文件的下载。多线程下载文件之所以快,是因为其抢占的服务器资源多。如:假设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计算机中并非并发执行,而是由cpu划分时间片轮转执行,如果A应用使用了99条线程下载文件,那么相当于占用了99个用户的资源,假设一秒内cpu分配给每条线程的平均执行时间为10ms,A应用在服务器中一秒内就得到了990ms的执行时间,而其他应用在一秒内只有10ms的执行时间,就如同一个水龙头,每秒出水量相等的情况下,放990毫秒的水肯定比放10毫秒的水更多。
具体实现步骤:
将可执行文件youdao.exe文件放到tomcat服务器的\Tomcat 7.0\webapps\ROOT目录下面
,并启动服务器。
创建一个java工程MutilDownload.java
public class TestDownload{
private static final String path="http://171.39.164.16:8080/youdao.exe";
public static void main(String []args){
//打开IE,并且打开httpwatch,
//复制path到地址栏后,点击record后,将地址跳转,并点击用IE下载
//此时,httpwatch将出现如下信息
GET /youdao.exe HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)
//User-Agent:表明下载请求,如果是IE,则表明是IE.
Host: 171.39.164.16:8080
DNT: 1
Connection: Keep-Alive
//-------------------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"5255880-1323225008000"
Last-Modified: Wed, 07 Dec 2011 02:30:08 GMT
Content-Type: application/octet-stream
Content-Length: 5255880 //文件长度
Date: Sat, 31 Aug 2013 14:05:59 GMT
//有了这个信息后,就可以设置内容
}
}
1,首先得到下载文件的长度,然后设置本地文件的长度。
- HttpURLConnection getContentLength();
- RandomAccessFile file=new RandomAccessFile("xx.exe","rwd);
- file.setLength(fileSize);//设置本地文件的长度
3.使用Http 的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置
- HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194302");
4.保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始定稿数据
- RandomAccessFile threadfile=new RandomAccessFile("xxx.exe","rwd);
- threadfile.seek(2097162);
具体代码:
- package org.itcast.download;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.URL;
- public class TestDownload {
- public static final String path="http://171.39.164.61:8080/youdao.exe";
- public static void main(String[] args)throws Exception {
- URL url=new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setReadTimeout(5000);
- conn.setRequestProperty("User-Agent","Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)");
- int code=conn.getResponseCode();
- if(code==200){
- int len=conn.getContentLength(); //取得要下載文件的大小
- //1.设置本地文件,通过方法getFileName取得文件名,并且加入rwd的模式
- RandomAccessFile file=new RandomAccessFile(getFileName(path),"rwd" );
- file.setLength(len);//设置本地文件大小 跟服务器文件大小 一致
- //2.设置3个线程,并计算每个线程下载的大小
- int threadnum=3;//线程个数
- int blocksize=len/threadnum;
- //线程1:从0到blocksize
- //线程2:从1*blocksize到2*blocksize
- //线程3:从2*blocksize到文件末尾
- //3.接下来将创建一个下载的类DownloadTask.java
- //4.这样就可以将文件下载
- for(int i=0;i<threadnum;i++){
- int startposition=1*blocksize;
- int endposition=(i+1)*blocksize;
- if(i==(threadnum-1)){
- //最后一个线程
- endposition=len;
- }
- DownloadTask task=new DownloadTask(i,path,startposition, endposition);
- task.start();
- }
- }
- }
- public static String getFileName(String path){//获取文件名”youdao.exe“的方法
- int start =path.lastIndexOf("/")+1;//开始的位置
- return path.substring(start,path.length());
- }
- }
- class DownloadTask extends Thread{
- public String path="http://171.39.164.16:8080/youdao.exe";
- int threadid;
- String filepath;
- int startposition;
- int endposition;
- public DownloadTask(int threadid, String filepath, int startposition,
- int endposition ) {
- this.threadid = threadid;
- this.filepath = filepath;
- this.startposition = startposition;
- this.endposition = endposition;
- }
- @Override
- public void run() {
- try {
- URL url=new URL(filepath);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- //3.使用Http 的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置
- //HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194302");
- conn.setRequestProperty("Range","bytes="+startposition+"-"+endposition);
- //把上面“经典”的配置配置下来
- conn.setRequestMethod("GET");
- conn.setReadTimeout(5000);
- conn.setRequestProperty("User-Agent","Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)");
- //取得 输入流
- InputStream is=conn.getInputStream();
- RandomAccessFile file=new RandomAccessFile(getFileName(path),"rwd");
- //设置数据从哪个位置开始写
- file.seek(startposition);
- byte[]buffer=new byte[1024];
- int len=0;
- if((len=is.read())!=-1){
- file.write(buffer,0,len);
- }
- file.close();
- System.out.println("线程"+threadid+"下载完毕!");
- } catch (Exception e) {
- e.printStackTrace();
- }
- super.run();
- }
- public static String getFileName(String path){//获取文件名”youdao.exe“的方法
- int start =path.lastIndexOf("/")+1;//开始的位置
- return path.substring(start,path.length());
- }
- }