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

来源:互联网 发布:福岛核事故 知乎 编辑:程序博客网 时间:2024/06/06 19:09

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

单重字面看异步所以需要线程;多线程所以需要有多个线程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 exceptione.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;}@Overridepublic 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