URL的单线程下载和多线程下载

单线程下载:

       1.定义网络资源地址

        2.打开连接

        3.获取输入流,定义输出流

        4.下载文件

        好处:不会对服务器造成压力

        弊端:当有多个进程时,CPU不会分配资源给其他线程,处理时间会变长。

多线程下载:

        跟单线程下载逻辑是相同的,主要在第三部有改进,将线程分块进行下载以此提高效率。

ps:若文件过大,多线程下载会创建N个线程,容易耗尽内存资源,所以代码中设置了下载数量,

    若下载到达5个线程,不再新增下载线程,等到下载子线程下载完成,在创建新的下载线程 

        

package com.yc.demo.multidown;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;

import com.yc.utils.CloseUtils;

public class Download {
	private int downSize=1024*1024;
	private String urlPath;
	private String filePath;
	
	//定义下载任务的计数器
	private int threadCount=0;

	public Download(String urlPath, String filePath) {
		this.urlPath = urlPath;
		this.filePath = filePath;
	}

	//单线程下载
	public void SingleDownload() throws IOException{
		InputStream in=null;
		FileOutputStream out=null;
		try{
			//定义网络资源地址
			URL url=new URL(urlPath);
			//打开连接
			URLConnection con=url.openConnection();
			//获取输入流
			in=con.getInputStream();
			//截取文件名()
			String fileName=urlPath.substring(urlPath.lastIndexOf("/")+1);
			//定义文件输出流
			out=new FileOutputStream(filePath+"/"+fileName);
			//下载文件
			byte[] b=new byte[1024];
			int count;
			int countSum=0;
			int rate=0;
			int filesize=con.getContentLength();  //文件长度
			while((count=in.read(b))>0){
				countSum+=count;
				int curRate=(int)( ( (float)countSum/(float)filesize ) *100 );
				if(curRate>rate){
					rate=curRate;
					System.out.println("文件下载进度:"+rate+"%");
				}
				out.write(b, 0, count);
			}
			System.out.println("下载完毕");
		}finally{
			in.close();
			out.close();
		}
	}

	//多线程下载
	public void multiDownload() throws IOException{
		//定义网络资源地址
		URL url=new URL(urlPath);
		//打开连接
		URLConnection con=url.openConnection();
		//截取文件名()
		String fileName=urlPath.substring(urlPath.lastIndexOf("/")+1);
		int filesize=con.getContentLength();  //定义随机访问文件对象
		//计算文件分段的段数
		int downLength=filesize/downSize;
		downLength+=filesize%downSize==0 ? 0:1;
		//定义final变量给匿名类使用
		final int fDownLength=downLength;
		for(int i=0;i<downLength;i++){
			//定义final变量给匿名类使用
			final int fi=i;
			synchronized (this) {
				if(threadCount>5){
					try {
						wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				threadCount++;	//每创建一个线程计数器+1
			}
			
			new Thread(){
				//获取输入流
				public void run(){
					System.out.println("开始分段下载任务:"+fi);
					//打开连接
					InputStream subIn=null;
					RandomAccessFile subOut=null;
					try {
						URLConnection subCon = url.openConnection();
						subIn=subCon.getInputStream();
						//定义随机访问文件对象
						subOut=new RandomAccessFile(filePath+"/"+fileName,"rw");

						//计算下载的起始位置
						int beginPos=fi*downSize;
						int endPos;
						//最后一段,并且未整除
						if(fi==fDownLength-1 && filesize%downSize>0){
							endPos=beginPos+filesize%downSize;
						}else{
							endPos=beginPos+downSize;
						}
						//输入流和输出流同时跳过beginPos个字节
						subIn.skip(beginPos);  
						subOut.seek(beginPos); 
						//统计下载的数量
						int curPos=beginPos;
						//下载文件
						byte[] b=new byte[1024];
						while(true){
							if(curPos<endPos){
								int count=0;
								if(endPos-curPos<1024){
									count=subIn.read(b, 0, endPos-curPos);
								}else{
									count=subIn.read(b);
								}
								if(count>0){
									subOut.write(b, 0, count);
									curPos+=count;
								}else{
									break;
								}
							}else{
								break;
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}finally {
						CloseUtils.close(subIn,subOut);
					}
					System.out.println("分段下载任务完成:"+fi);
					//通知Download.this继续进行新的线程下载
					synchronized (Download.this) {
						Download.this.notify();
						Download.this.threadCount--;
					}
				}
			}.start();
		}
		
		//System.out.println("下载完毕");
		
	}

	/**
	 * 单线程下载,使用main方法实现
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		Download down=new Download("http://data.5sing.kgimg.com/G131/M09/03/0D/ww0DAFr3nF-AG3w-AJXnKJqip8Y361.mp3","d:/aaa/");
		down.multiDownload();
	}
}


猜你喜欢

转载自blog.csdn.net/qq_42461639/article/details/80774350
今日推荐