Java、Android中的多线程异步下载
2015-06-01 21:30
274 查看
在多线程异步下载中,各种语言都是类似的。
单重字面看异步所以需要线程;多线程所以需要有多个线程Tread;下载所以需要把Http请求写入文件。
按照这样的思路就需要建立http链接,建立下载的临时文件;
需要计算每个线程的下载开始和结束位置,并进行请求。
下面给出完整的例子:
下面再放一个参考资料,里面分析了下载时每次HTTP请求头的状态
http://www.cnblogs.com/diyunpeng/archive/2011/12/29/2305702.html
单重字面看异步所以需要线程;多线程所以需要有多个线程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
相关文章推荐
- Android BroadCast (一)
- Android之DDMS无法查看/data/data目录
- Android BroadCast (二)
- Android 序列化比对
- Android 进程间通信IPC_AIDL
- android开发(42) 使用andorid操作蓝牙打印机
- EventBus for Android 源码分析
- Android 启动模式
- Android手机屏幕之asm.jar
- Android View 分析(上)
- Android View 分析(中)
- Android View 分析(下)
- Android AsyncTask详解
- Android Service
- Android Socket
- 如何指定让Android的NDK工具编译出Release版本或Debug版本的Native程序
- Android中的设计模式
- Android通过webservice操作数据库1(查询数据库)
- 关于android移动动画和缩放动画的构造函数简介
- Android Property介绍