Java、Android中的多线程异步下载

10 篇文章 0 订阅

在多线程异步下载中,各种语言都是类似的。

单重字面看异步所以需要线程;多线程所以需要有多个线程Tread;下载所以需要把Http请求写入文件。

按照这样的思路就需要建立http链接,建立下载的临时文件;

需要计算每个线程的下载开始和结束位置,并进行请求。

下面给出完整的例子:

package download;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;


public class MultiDownload {
	
	public static int threadCount = 3;
	public static String path = "http://dldir1.qq.com/qqfile/qq/QQ7.2/14810/QQ7.2.exe";
	//public static String path = "http://hiphotos.baidu.com/240728057/pic/item/6a50e38242aad8f60cf4d2b3.jpg";

	public static void main(String[] args) {
		try {
			URL url = new URL(path);
			HttpURLConnection conn  =  (HttpURLConnection)url.openConnection();
			conn.setRequestMethod("GET");
			conn.setReadTimeout(5000);
			conn.setConnectTimeout(5000);
			if (conn.getResponseCode() ==200){
				//下载文件的大小
				int length = conn.getContentLength();
				//创建临时文件的路径和名称
				File file = new File(getFileName(path));
				//创建速记存储文件对象
				RandomAccessFile raf = new RandomAccessFile(file, "rwd");
				//设置临时文件大小
				raf.setLength(length);
				//计算每个线程下载的字节数
				int size = length / threadCount;
				for (int i = 0; i<threadCount;i++){
					//计算每个线程下载数据的开始和结束位置
					int startIndex = i*size;
					int endIndex = (i+1)*size -1;
					//如果是最后一个线程,那么借宿位置特殊处理
					if(i==threadCount-1){
						endIndex = length -1;
					}
					System.out.println("线程"+i+"已经启动,下载位置为:"+startIndex+"--------->"+endIndex);
					//开始线程
					new DownloadThread(i, startIndex, endIndex,url).start();
				}
			}
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	public static String getFileName(String path){
		int index = path.lastIndexOf("/");
		return path.substring(index+1);
	}
}
/**
 * @author frozen cloud
 *下载线程
 */
class DownloadThread extends Thread{
	int threadId;
	int startIndex;
	int endIndex;
	URL url;
	
	public DownloadThread(int threadId,int startIndex,int endIndex,URL url) {
		super();
		this.threadId = threadId;
		this.startIndex = startIndex;
		this.endIndex = endIndex;
		this.url = url;
	}
	@Override
	public void run(){
		try {
			HttpURLConnection conn  =  (HttpURLConnection)url.openConnection();
			conn.setRequestMethod("GET");
			conn.setReadTimeout(5000);
			conn.setConnectTimeout(5000);
			//设置请求的数据的范围
			conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
			
			if (conn.getResponseCode() == 206){
				InputStream is = conn.getInputStream();
				int len = 0;
				byte[] b = new byte[1024];
				
				int total =0;
				//创建临时文件的路径和名称
				File file = new File(MultiDownload.getFileName(MultiDownload.path));
				//创建速记存储文件对象
				RandomAccessFile raf = new RandomAccessFile(file, "rwd");
				//设置线程写入数据的开始位置
				raf.seek(startIndex);
				while((len = is.read(b))!=-1){
					raf.write(b,0,len);
					total +=len;
					System.out.println("线程"+threadId+"总共下载了:"+total);
				}
				raf.close();
				System.out.println("线程下载结束:"+threadId);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
这里需要注意的是,在线程中,状态码需要是206而不是请求成功时的200。


下面再放一个参考资料,里面分析了下载时每次HTTP请求头的状态

http://www.cnblogs.com/diyunpeng/archive/2011/12/29/2305702.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值