zoukankan      html  css  js  c++  java
  • JAVA实现多线程下载

    1.开启三个下载线程;
    2.开启一个监视线程,用于查看下载进度。

    完整代码

    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    public class JavaMultiThreadDown {
    	public static void main(String[] args) throws Exception {
    		// 下载路径使用的是百度网盘上文件的下载路径
    		String _下载路径 = "https://bjbgp01.baidupcs.com/file/1d9cedae59e9042a85cb0b98b4340c9c?bkt=p3-00007b4ef6ea09a0f17a89712f670b4985c6&fid=3255250463-250528-363978972781448&time=1554510897&sign=FDTAXGERQBHSKfW-DCb740ccc5511e5e8fedcff06b081203-1Sm5YGIZMjBwhUyJY4n2UBJLkJ0%3D&to=75&size=5528379&sta_dx=5528379&sta_cs=0&sta_ft=pdf&sta_ct=0&sta_mt=0&fm2=MH%2CQingdao%2CAnywhere%2C%2Chubei%2Cpbs&ctime=1554510826&mtime=1554510826&resv0=cdnback&resv1=0&vuk=3255250463&iv=2&htype=&newver=1&newfm=1&secfm=1&flow_ver=3&pkey=00007b4ef6ea09a0f17a89712f670b4985c6&expires=8h&rt=sh&r=458234945&mlogid=2211612084113124362&vbdid=1929586120&fin=%E4%B8%8B%E8%BD%BD%E6%B5%8B%E8%AF%95.pdf&fn=%E4%B8%8B%E8%BD%BD%E6%B5%8B%E8%AF%95.pdf&rtype=1&dp-logid=2211612084113124362&dp-callid=0.1.1&hps=1&tsl=0&csl=0&csign=4j3EXxSQdY9W8SenN6CIXXqjvfE%3D&so=0&ut=1&uter=4&serv=0&uc=4192912830&ti=90e00819b6f54250603b4062c17fc35df0cc8c47b8fc9467&by=themis";
    		String _本地文件 = "有那种网站嘛?有,还是合集哦.pdf";
    		int _线程数量 = 3;
    		// 初始化DownUtil对象
    		final Downloader downLoader = new Downloader(_下载路径, _本地文件, _线程数量);
    		// 开始下载
    		downLoader.download();
    	}
    }
    class Downloader {
    	private String netUrl;// 下载资源的路径
    	private String saveFile;// 下载的路径(含文件名)
    	private int threadNum;// 线程数量
    	private DownLoaderThread[] threads;// 线程数组
    	private int fileSize;// 下载的文件的Size
    	public Downloader(String netUrl, String targetFile, int threadNum) {
    		this.netUrl = netUrl;
    		this.saveFile = targetFile;
    		this.threadNum = threadNum;
    		// 初始化线程数组
    		this.threads = new DownLoaderThread[threadNum];
    	}
    	public void download() throws Exception {
    		URL url = new URL(netUrl);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setConnectTimeout(5 * 1000);
    		conn.setRequestMethod("GET");
    		fileSize = conn.getContentLength();
    		System.out.println("待下载文件的大小为:" + (double) (fileSize / 1024) / 1024 + "M");
    		conn.disconnect();
    		// 分部下载
    		int currentPartSize = fileSize / threadNum + 1;
    		RandomAccessFile file = new RandomAccessFile(saveFile, "rw");
    		// 设置本地文件大小
    		file.setLength(fileSize);
    		file.close();
    		// 开启下载线程
    		for (int i = 0; i < threadNum; i++) {
    			// 计算每条线程的下载的开始位置
    			int startPos = i * currentPartSize;
    			// 每个线程使用一个RandomAccessFile进行下载
    			RandomAccessFile currentPart = new RandomAccessFile(saveFile, "rw");
    			// 定位线程的下载位置
    			currentPart.seek(startPos);
    			// 创建下载线程
    			threads[i] = new DownLoaderThread(startPos, currentPartSize, currentPart);
    			// 启动下载线程
    			threads[i].start();
    		}
    		Thread overseer = new Thread(new Overseer(this));
    		overseer.start();
    	}
    	private class DownLoaderThread extends Thread {
    		private int startPos;// 当前线程的下载位置
    		private int currentPartSize;// 当前线程负责下载的文件大小
    		private RandomAccessFile currentPart;// 当前线程需要下载的文件块
    		public int length;// 该线程已下载的字节数
    		public DownLoaderThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
    			this.startPos = startPos;
    			this.currentPartSize = currentPartSize;
    			this.currentPart = currentPart;
    		}
    		@Override
    		public void run() {
    			try {
    				URL url = new URL(netUrl);
    				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    				conn.setConnectTimeout(5 * 1000);
    				conn.setRequestMethod("GET");
    				InputStream inStream = conn.getInputStream();
    				// 跳过不需要下载的部分
    				inStream.skip(this.startPos);
    				byte[] buffer = new byte[1024];
    				int hasRead = 0;
    				// 读取网络数据,并写入本地文件
    				while (length < currentPartSize && (hasRead = inStream.read(buffer)) != -1) {
    					currentPart.write(buffer, 0, hasRead);
    					// 累计该线程下载的总大小
    					length += hasRead;
    				}
    				currentPart.close();
    				inStream.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	private class Overseer implements Runnable {
    		Downloader downLoader;
    		Overseer(Downloader downLoader) {
    			this.downLoader = downLoader;
    		}
    		@Override
    		public void run() {
    			double p;
    			while ((p = getCompleteRate()) < 100) {
    				// 隔段时间查询一次任务完成进度,
    				System.out.println("已完成:" + p + "%");
    				try {
    					Thread.sleep(1500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			System.out.println("下载完毕");
    		}
    		// 获取下载的完成百分比
    		private double getCompleteRate() {
    			// 统计多条线程已经下载的总大小
    			int sumSize = 0;
    			for (int i = 0; i < threadNum; i++) {
    				sumSize += threads[i].length;
    			}
    			// 返回已经完成的百分比
    			int percent = (int) (sumSize * 100.0 / fileSize);
    			return percent;
    		}
    	}
    }
    

    运行结果

    待下载文件的大小为:5.271484375M
    已完成:0.0%
    已完成:3.0%
    已完成:13.0%
    已完成:21.0%
    已完成:29.0%
    已完成:33.0%
    已完成:35.0%
    已完成:50.0%
    已完成:64.0%
    已完成:66.0%
    已完成:66.0%
    已完成:66.0%
    已完成:66.0%
    已完成:66.0%
    已完成:73.0%
    已完成:90.0%
    下载完毕

  • 相关阅读:
    GitTortoise + Git Source Control Provider使用笔记
    Manage your ViewEngine(Wirte by myself)
    JSON DATE 转换标准的一些资料(收集)
    IE 6崩溃第一条禁用所有插件
    invalid label problem
    使用jQuery Html() 作为客户端htmlEncode的问题
    在WIN7下使用XP Mode安装IE6+
    Jquery simple friendly scroll
    Cygwin使用指南
    How to enable Plain Text Password
  • 原文地址:https://www.cnblogs.com/tigerlion/p/10661367.html
Copyright © 2011-2022 走看看