• 多线程下载文件


        使用多线程下载文件可以更快地完成文件的下载。多线程下载文件之所以快,是因为其抢占的服务器资源多。如:假设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计算机中并非并发执行,而是由cpu划分时间片轮转执行,如果A应用使用了99条线程下载文件,那么相当于占用了99个用户的资源,假设一秒内cpu分配给每条线程的平均执行时间为10ms,A应用在服务器中一秒内就得到了990ms的执行时间,而其他应用在一秒内只有10ms的执行时间,就如同一个水龙头,每秒出水量相等的情况下,放990毫秒的水肯定比放10毫秒的水更多。

        具体实现步骤:

    将可执行文件youdao.exe文件放到tomcat服务器的Tomcat 7.0webappsROOT目录下面
    ,并启动服务器。

    创建一个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);//设置本地文件的长度

    2.根据文件长度和线程数计算每个线程下载的数据长度和下载位置。如:文件的长度为6M,线程数为3,则每个线程下载的数据长度为2M。
    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());
    	}
    }




  • 相关阅读:
    C#概述
    作为一个程序员小小感悟!!
    c# 合并两个DataTable
    C# FastReport .NET打印
    c# System.Net.Sockets =》TcpListener用法
    开博第一章
    Vue 报错 Uncaught (in promise)
    ASP.NET MVC 中的过滤器
    SpringBoot 打包成war
    SprintBoot 实现上传下载
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3295240.html
Copyright © 2020-2023  润新知