文档章节

java实现的多线程下载器

zhangyujsj
 zhangyujsj
发布于 2015/07/08 16:28
字数 791
阅读 66
收藏 0
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.HttpURLConnection;

public class DownUtil {
	private String mPath; // 就是整个的URL地址
	private String mTargetFileName;// 文件名
	private int mThreadNum; // 线程数目
	private DownThread[] mThreads; // 自己的下载线程数组
	private int mFileSize;

	public DownUtil(String path, String targetFile, int threadNum) {
		mPath = path;
		mTargetFileName = targetFile;
		mThreadNum = threadNum;
		mThreads = new DownThread[mThreadNum]; // 这里只是new了一个引用的数组
	}

	/**
	 * 下载函数 注意一个概念,URL类是远程服务器上资源的描述符,URLConnection是app和远程资源的连接
	 * 
	 * @throws IOException
	 * */
	public void download() throws IOException {
		// 1 创建URL对象
		URL url = new URL(mPath);
		// A 调用URL对象的openConnection()创建URLConnection对象
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		// B 设置URLConnection的参数和普通请求属性
		conn.setConnectTimeout(5 * 100);
		// C 设置请求头字段 方法很多setAllowUserInterface(),setDoInput(),setDoOutput()
		conn.setRequestMethod("GET");
		conn.setRequestProperty(
				"Accept",
				"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,"
						+ " application/vnd.ms-excel, application/vnd.ms-powerpoint,"
						+ " application/msword, application/x-silverlight, "
						+ "application/x-shockwave-flash, */* "); // 客户端可识别的内容类型列表
		conn.setRequestProperty("Accept-Language", "zh-CN");
		conn.setRequestProperty("Charset", "UTF-8");
		conn.setRequestProperty("Connection", "Keep-Alive");
		// D 发送GET请求则调用connect建立和远程资源的连接;发送POST请求则获取URLConnection对象的输出流
		// E 访问远程资源的头字段或者通过输入流读取远程资源的数据
		// 2 获取指定URL对象所指向资源的大小
		mFileSize = conn.getContentLength(); // 这里做这么多事只是为了取得这个资源大小而已
		conn.disconnect();
		// 3 本地磁盘上创建一个与网络资源同样大小的空文件
		RandomAccessFile targetFile = new RandomAccessFile(mTargetFileName,
				"rw");
		targetFile.setLength(mFileSize);
		targetFile.close();
		// 4 分配各线程下载文件的各个部分
		int currentPartSize = mFileSize / mThreadNum + 1;
		// 5 依次创建,启动线程进行下载
		for (int i = 0; i < mThreadNum; ++i) {
			// 计算每一个线程下载的开始位置
			int startPos = i * currentPartSize;
			// 每个线程使用一个RandomAccessFile对象进行下载
			RandomAccessFile currentPart = new RandomAccessFile(
					mTargetFileName, "rw");
			// 定位这个线程的下载位置
			currentPart.seek(startPos);
			// 创建并启动线程
			mThreads[i] = new DownThread(startPos, currentPartSize, currentPart);
			mThreads[i].start();
		}
	}

	/**
	 * 实现对下载进度的查询
	 * */
	public double getCompleteRate() {
		int sumSize = 0;
		for (int i = 0; i < mThreadNum; ++i) {
			sumSize += mThreads[i].getLength(); // length变量表示线程当前已经下载的量
		}
		return sumSize * 1.0 / mFileSize;
	}

	/**
	 * 下载子线程
	 * */
	private class DownThread extends Thread {
		// 下载起始位置
		private int mStartPos;
		// 负责的文件大小
		private int mCurrentPartSize;
		// 当前线程需要下载的文件块
		private RandomAccessFile mCurrentPart;

		private volatile int mLength;

		public DownThread(int startPos, int currentPartSize,
				RandomAccessFile currentPart) {
			mStartPos = startPos;
			mCurrentPart = currentPart;
			mCurrentPartSize = currentPartSize;
		}

		public int getLength() {
			return mLength;
		}

		public void run() {
			// 下载的过程就是从url的输入流中把数据取出来存到文件中去
			try {
				URL url = new URL(mPath);
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setConnectTimeout(500);
				conn.setRequestMethod("GET"); // 起始行 中包括method 和url以及http版本
				conn.setRequestProperty(
						"Accept",
						"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,"
								+ " application/vnd.ms-excel, application/vnd.ms-powerpoint,"
								+ " application/msword, application/x-silverlight, "
								+ "application/x-shockwave-flash, */* "); // 客户端可识别的内容类型列表
				conn.setRequestProperty("Accept-Language", "zh-CN");
				conn.setRequestProperty("Charset", "UTF-8");
				conn.setRequestProperty("Connection", "Keep-Alive");
				InputStream inStream = conn.getInputStream();
				inStream.skip(mStartPos); 
				byte[] buffer = new byte[1024];
				int hasRead = 0;
				while(mLength < mCurrentPartSize 
						&& (hasRead = inStream.read(buffer)) > 0) { // 没下完,同时每次都下到了数据,用自己的raf写入
					mCurrentPart.write(buffer,0,hasRead);
					mLength += hasRead;
				}
				// 这里表示该线程负责部分下完,释放资源
				mCurrentPart.close();
				inStream.close(); // 关闭url对象的输入流
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}


本文转载自:

zhangyujsj
粉丝 24
博文 358
码字总数 224241
作品 0
广州
私信 提问
Apache Tomcat 8.5.33 发布,知名 Web 应用服务器

Apache Tomcat 8.5.33 发布了,Tomcat 是 Java Servlet、JavaServer Pages、Java 表达式语言和 Java WebSocket 技术的开源实现,是一个免费的开放源代码的 Web 应用服务器。 Apache Tomcat ...

h4cd
2018/08/21
1K
4
tomcat7 cpu 占用率过高调整

之前在在catalina.sh中简单设置JAVAOPTS=-Xms1024m -Xmx2048m,没起作用,CPU还是超高,机器内存限制再大也设不了了,转而到启动脚本里设置了这一堆参数,没有一个个的排查,到底哪个参数起作...

youway
2015/01/28
987
2
sharding-jdbc 1.3.2,当当 JDBC 增强驱动

Sharding-JDBC 1.3.2 发布了,Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据库分库分表 访问。Sharding-JDBC是继dubbox和...

淡漠悠然
2016/09/13
2.7K
2
interview questions

1.java中为什么会出现多线程? Java内存模型决定了 CPU 不能 完全利用,为了充分利用CPU,所以产生了多线程技术。 2.多线程中,如果不调用start方法,直接调用run方法会发生什么? 只有调用T...

无断无灭无住无念
2017/11/06
29
0
TigerVNC 1.8.0 发布,VNC 客户端和服务器

TigerVNC 1.8.0 的完整版本现已推出。自上次发布以来,已经有很多变化,值得关注的是: Java 客户端重大变更,以匹配本机客户端的外观和行为 在 Java客户端进行多线程解码的初始工作 使用 Xv...

局长
2017/05/17
2.2K
3

没有更多内容

加载失败,请刷新页面

加载更多

JIT编程与方法内联

JIT的比较冷门,首先你要读一下这两篇 帖子: 《面向JIT编程-方法内联》 https://blog.csdn.net/u012834750/article/details/79488572 《浅谈对JIT编译器的理解》 https://www.cnblogs.com/...

爱吃窝窝头
18分钟前
3
0
基于TCP的RPC实现

RPC即远程服务调用 出现原因:随着项目越来越大,访问量越来越大,为了突破性能瓶颈,需要将项目拆分成多个部分,这样比起传统的项目都是本地内存调用,分布式的项目之间需要在网络间进行通信...

少年已不再年少
28分钟前
5
0
OSChina 周二乱弹 —— 他只能用这个办法劝你注意身体了

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @-冰冰棒- :#今日歌曲推荐# Kodaline《High Hopes》 《High Hopes》- Kodaline 手机党少年们想听歌,请使劲儿戳(这里) @xiaoshiyue :仙女...

小小编辑
49分钟前
1K
21
Spring Boot Actuator 整合 Prometheus

简介 Spring Boot 自带监控功能 Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、环境变量、日志信息、线程信息等。这一节结合 Prometheus 、Grafana 来更加直观...

程序员果果
58分钟前
11
0
Linux文件查找命令详解

对于文件查找,我们最好用的还是属于find命令了,在说find命令之前,先把另外几个查找命令介绍一下。 目录 0x01 查询命令介绍 0x02 find命令介绍 0x01 查询命令介绍 在介绍之前,首先先了解一...

无心的梦呓
58分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部