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%
下载完毕

原文地址:https://www.cnblogs.com/tigerlion/p/10661367.html