多线程断点下载


所谓断点下载,是指因异常原因(如:断电)导致下载失去连接后,重新下载会继续进度,而不会从头开始。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DecimalFormat;


/**
 * 多线程断点下载工具 
 * 1.通过提供的网络文件地址,下载该文件
 * 2.使用多个线程同时下载,并且实时更新下载进度(0%~100%)
 * 3.实现断点功能
 */
public class ThreadsNetDownload extends Thread {


	private File targetFile; // 目标文件
	private URL url; // 打开链接
	private long length; // 下载资源的大小
	private static long proccess; // 下载进程
	private int count;


	public ThreadsNetDownload(File targetFile, URL url, long length) {
		super();
		this.targetFile = targetFile;
		this.url = url;
		this.length = length;
	}


	@Override
	public void run() {
		if (this.getName().equals("下载线程1")) {
			Download(0, length / 4);
		} else if (this.getName().equals("下载线程2")) {
			Download(length / 4, length / 2); 
		} else if (this.getName().equals("下载线程3")) {
			Download(length / 2, length * 3 / 4); 
		} else {
			Download(length * 3 / 4, length); 
		}
		if(proccess/length == 1){
			System.out.println("当前下载进度:100%");
			System.out.println("拷贝完成!!");
		}
	}


	/**
	 * 下载文件
	 */
	private void Download(long start, long end) {


		InputStream is;
		BufferedInputStream bis = null;
		RandomAccessFile writer = null;
		try {


			// 打开一个URL链接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			// 设置请求方法(get请求)
			conn.setRequestMethod("GET");
			// 获取响应的状态码
			int code = conn.getResponseCode();
			// 判断是否响应成功
			if (code == HttpURLConnection.HTTP_OK) {
				is = conn.getInputStream();
				bis = new BufferedInputStream(is);
			} else {
				System.out.println("资源无响应。");
			}


			writer = new RandomAccessFile(targetFile, "rw");
			
//			start += getRecord();
			bis.skip(start);
			writer.seek(start);
			byte[] b = new byte[1024];
			int len = 0;
			
			while ((len = bis.read(b)) != -1 && count <= end - start) {
				count += len;
				//记录当前文件下载到的位置
				setRecord(count);
//				System.out.println(this.getName()+"记录进度:" + getRecord()/1024);
				//下载进度
				proccess += len;
				if(proccess/length < 1){
					System.out.println("当前下载进度:" + new DecimalFormat("##.##%").format((double)proccess/length));
				}
				writer.write(b, 0, len);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				if (writer != null)
					writer.close();
				if (bis != null)
					bis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}


	/**
	 * 从文件中读取进度
	 * @return
	 */
	private long getRecord() {
		long rec = 0L;
		File file = new File(targetFile.getParent(),this.getName()+".txt");
		RandomAccessFile reader = null;
		try {
			reader = new RandomAccessFile(file,"r");
			rec = reader.readLong();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			if(reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return rec;
	}


	/**
	 * 记录当前进度到文件中
	 * @param count
	 */
	private void setRecord(long count) {
		
		File file = new File(targetFile.getParent(),this.getName()+".txt");
		RandomAccessFile writer = null;
		try {
			writer = new RandomAccessFile(file,"rw");
			writer.writeLong(count);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			if(writer != null)
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		
	}


	public static void main(String[] args) throws IOException,
			URISyntaxException {


		String s = "http://192.168.46.254:8888/easyBuy/images/plmm.jpg";
		// 根据字符串构建一个URL对象
		URL url = new URL(s);
		// 打开一个URL链接
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		// 设置请求方法(get请求)
		conn.setRequestMethod("GET");
		long len = conn.getContentLength();


		// 准备目标文件
		File f = new File(
				"C:\\Documents and Settings\\Administrator\\桌面\\test",
				s.substring(s.lastIndexOf("/")));


		ThreadsNetDownload tnd1 = new ThreadsNetDownload(f, url, len);
		ThreadsNetDownload tnd2 = new ThreadsNetDownload(f, url, len);
		ThreadsNetDownload tnd3 = new ThreadsNetDownload(f, url, len);
		ThreadsNetDownload tnd4 = new ThreadsNetDownload(f, url, len);


		tnd1.start();
		tnd1.setName("下载线程1");
		tnd2.start();
		tnd2.setName("下载线程2");
		tnd3.start();
		tnd3.setName("下载线程3");
		tnd4.start();
		tnd4.setName("下载线程4");


	}
}


注意了,该多线程断点下载,其中的“多线程”并不能使你的下载速度加快,主要是提升网络带宽的利用率和主机cpu的利用率; 决定你下载速度的,一个是你的带宽,另一个是服务器提供的节点位置与你的距离。

那么有人就问了,“哎,博主这篇博客的对我们的作用何在呢?”

“有的,一切为了java的学习...”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值