您的位置:首页 > 移动开发 > Android开发

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

2015-06-01 21:30 274 查看
在多线程异步下载中,各种语言都是类似的。

单重字面看异步所以需要线程;多线程所以需要有多个线程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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: