多线程下载文件

来源:互联网 发布:holy shit 知乎 编辑:程序博客网 时间:2024/05/16 01:57

转载自: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,首先得到下载文件的长度,然后设置本地文件的长度。

[java] view plaincopy
  1. HttpURLConnection getContentLength();  
  2. RandomAccessFile file=new RandomAccessFile("xx.exe","rwd);  
  3. file.setLength(fileSize);//设置本地文件的长度  
2.根据文件长度和线程数计算每个线程下载的数据长度和下载位置。如:文件的长度为6M,线程数为3,则每个线程下载的数据长度为2M。
3.使用Http 的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置

[java] view plaincopy
  1. HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194302");  

4.保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始定稿数据 

[java] view plaincopy
  1. RandomAccessFile threadfile=new RandomAccessFile("xxx.exe","rwd);  
  2. threadfile.seek(2097162);  

具体代码:

[java] view plaincopy
  1. package org.itcast.download;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.RandomAccessFile;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7.   
  8. public class TestDownload {  
  9.   
  10.     public static final String path="http://171.39.164.61:8080/youdao.exe";  
  11.     public static void main(String[] args)throws Exception {   
  12.   
  13.         URL url=new URL(path);  
  14.         HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  15.         conn.setRequestMethod("GET");  
  16.         conn.setReadTimeout(5000);  
  17.         conn.setRequestProperty("User-Agent","Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)");  
  18.         int code=conn.getResponseCode();  
  19.         if(code==200){  
  20.             int len=conn.getContentLength(); //取得要下載文件的大小   
  21.             //1.设置本地文件,通过方法getFileName取得文件名,并且加入rwd的模式  
  22.             RandomAccessFile file=new RandomAccessFile(getFileName(path),"rwd" );  
  23.             file.setLength(len);//设置本地文件大小 跟服务器文件大小 一致  
  24.             //2.设置3个线程,并计算每个线程下载的大小   
  25.             int threadnum=3;//线程个数   
  26.             int blocksize=len/threadnum;  
  27.             //线程1:从0到blocksize  
  28.             //线程2:从1*blocksize到2*blocksize  
  29.             //线程3:从2*blocksize到文件末尾   
  30.             //3.接下来将创建一个下载的类DownloadTask.java  
  31.             //4.这样就可以将文件下载  
  32.               
  33.             for(int i=0;i<threadnum;i++){  
  34.                 int startposition=1*blocksize;  
  35.                 int endposition=(i+1)*blocksize;  
  36.                 if(i==(threadnum-1)){  
  37.                     //最后一个线程  
  38.                     endposition=len;  
  39.                 }  
  40.                 DownloadTask task=new DownloadTask(i,path,startposition, endposition);  
  41.                 task.start();  
  42.             }  
  43.         }  
  44.       
  45.     }  
  46.     public static String getFileName(String path){//获取文件名”youdao.exe“的方法  
  47.         int start =path.lastIndexOf("/")+1;//开始的位置  
  48.         return path.substring(start,path.length());  
  49.     }  
  50.   
  51. }  
  52.   
  53.   
  54. class DownloadTask extends Thread{  
  55.     public  String path="http://171.39.164.16:8080/youdao.exe";  
  56.     int threadid;  
  57.     String filepath;  
  58.     int startposition;  
  59.     int endposition;   
  60.     public DownloadTask(int threadid, String filepath, int startposition,  
  61.             int endposition ) {   
  62.         this.threadid = threadid;  
  63.         this.filepath = filepath;  
  64.         this.startposition = startposition;  
  65.         this.endposition = endposition;   
  66.     }  
  67.     @Override  
  68.     public void run() {   
  69.         try {  
  70.             URL url=new URL(filepath);  
  71.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  72.             //3.使用Http 的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置  
  73.             //HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194302");  
  74.             conn.setRequestProperty("Range","bytes="+startposition+"-"+endposition);  
  75.             //把上面“经典”的配置配置下来  
  76.             conn.setRequestMethod("GET");  
  77.             conn.setReadTimeout(5000);  
  78.             conn.setRequestProperty("User-Agent","Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)");  
  79.             //取得 输入流  
  80.             InputStream is=conn.getInputStream();  
  81.             RandomAccessFile file=new RandomAccessFile(getFileName(path),"rwd");  
  82.             //设置数据从哪个位置开始写  
  83.             file.seek(startposition);  
  84.             byte[]buffer=new byte[1024];  
  85.             int len=0;  
  86.             if((len=is.read())!=-1){  
  87.                 file.write(buffer,0,len);  
  88.             }  
  89.             file.close();  
  90.             System.out.println("线程"+threadid+"下载完毕!");  
  91.         } catch (Exception e) {   
  92.             e.printStackTrace();  
  93.         }  
  94.         super.run();  
  95.     }  
  96.     public static String getFileName(String path){//获取文件名”youdao.exe“的方法  
  97.         int start =path.lastIndexOf("/")+1;//开始的位置  
  98.         return path.substring(start,path.length());  
  99.     }  
  100. }  
0 0
原创粉丝点击