android --多线程下载

多线程下载文件的过程是: 

   (1)首先获得下载文件的长度,然后设置本地文件的长度。

       HttpURLConnection.getContentLength();//获取下载文件的长度

      RandomAccessFile file = new RandomAccessFile("QQSetup.exe","rwd");

        file.setLength(filesize);//设置本地文件的长度

 

  (2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。

   
  如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示。

  

   例如10M大小,使用3个线程来下载,

    
   线程下载的数据长度   (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M

     
   下载开始位置:线程id*每条线程下载的数据长度 = ?

    
   下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?

 

  (3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,

     
   如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止

           代码如下:HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");

 

  (4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。

RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");

threadfile.seek(2097152);//从文件的什么位置开始写入数据

[java] view plain copy

 print?

  1. /**  
  2.  *多线程下载,UI更新类   
  3.  *@author young  
  4.  * */    
  5. public class MultiThreadDownload extends Thread{    
  6.     private static final String TAG = "MultiThreadDownload";    
  7.     /**每一个线程需要下载的大小 */    
  8.     private int blockSize;    
  9.     /*** 线程数量<br> 默认为5个线程下载*/    
  10.     private int threadNum = 5;    
  11.     /*** 文件大小 */    
  12.     private int fileSize;    
  13.     /** * 已经下载多少 */    
  14.     private int downloadSize;    
  15.     /**文件的url,线程编号,文件名称*/    
  16.     private String UrlStr,ThreadNo,fileName;    
  17.     /***保存的路径*/    
  18.     private String savePath;    
  19.     /**下载的百分比*/    
  20.     private int downloadPercent = 0;    
  21.     /**下载的 平均速度*/    
  22.     private int downloadSpeed = 0;    
  23.     /**下载用的时间*/    
  24.     private int usedTime = 0;    
  25.     /**当前时间*/    
  26.     private long curTime;    
  27.     /**是否已经下载完成*/    
  28.     private boolean completed = false;    
  29.     private Handler handler ;    
  30.     /**  
  31.      * 下载的构造函数    
  32.      * @param url  请求下载的URL  
  33.      * @param handler   UI更新使用  
  34.      * @param savePath  保存文件的路径  
  35.      */    
  36.     public MultiThreadDownload(Handler handler,String url,String savePath)    
  37.     {    
  38.         this.handler = handler;    
  39.         this.UrlStr = url;    
  40.         this.savePath = savePath;    
  41.         Log.e(TAG, toString());    
  42.     }    
  43.         
  44.     @Override    
  45.     public void run() {    
  46.             
  47.         FileDownloadThread[] fds = new FileDownloadThread[threadNum];//设置线程数量    
  48.         try {    
  49.             URL url = new URL(UrlStr);    
  50.             URLConnection conn = url.openConnection();    
  51.             fileSize = conn.getContentLength();    
  52.                 
  53.             this.fileName = FileUtil.getFileName(UrlStr);    
  54.             //只创建一个文件,saveFile下载内容    
  55.             File saveFile = new File(savePath+"/"+fileName);    
  56.             Log.e(TAG, "文件一共:"+fileSize+" savePath "+savePath+"  fileName  "+fileName);    
  57.                 
  58.             RandomAccessFile accessFile = new RandomAccessFile(saveFile,"rwd");    
  59.             //设置本地文件的长度和下载文件相同       
  60.             accessFile.setLength(fileSize);      
  61.             accessFile.close();    
  62.             //Handler更新UI,发送消息    
  63.             sendMsg(FileUtil.startDownloadMeg);    
  64.             //每块线程下载数据    
  65.             blockSize = ((fileSize%threadNum)==0)?(fileSize/threadNum):(fileSize/threadNum+1);    
  66.             Log.e(TAG, "每个线程分别下载 :"+blockSize);    
  67.                 
  68.             for (int i = 0; i < threadNum; i++) {    
  69.                 int curThreadEndPosition = (i+1)!=threadNum ? ((i+1)*blockSize-1) : fileSize;    
  70.                 FileDownloadThread fdt = new FileDownloadThread(url, saveFile, i*blockSize, curThreadEndPosition);    
  71.                 fdt.setName("thread"+i);    
  72.                 fdt.start();    
  73.                 fds[i]=fdt;    
  74.             }    
  75.             /**  
  76.              * 获取数据,更新UI,直到所有下载线程都下载完成。  
  77.              */    
  78.             boolean finished = false;    
  79.             //开始时间,放在循环外,求解的usedTime就是总时间    
  80.             long startTime = System.currentTimeMillis();    
  81.             while(!finished)    
  82.             {    
  83.                 downloadSize = 0;    
  84.                 finished = true;    
  85.                 for (int i = 0; i < fds.length; i++) {    
  86.                     downloadSize+= fds[i].getDownloadSize();    
  87.                     if(!fds[i].isFinished())    
  88.                     {    
  89.                         finished = false;    
  90.                     }    
  91.                 }    
  92.                 downloadPercent = (downloadSize*100)/fileSize;    
  93.                 curTime = System.currentTimeMillis();    
  94.                 System.out.println("curTime = "+curTime+" downloadSize = "+downloadSize+" usedTime "+(int) ((curTime-startTime)/1000));    
  95.                 usedTime = (int) ((curTime-startTime)/1000);    
  96.                     
  97.                 if(usedTime==0)usedTime = 1;      
  98.                 downloadSpeed = (downloadSize/usedTime)/1024;    
  99.                 sleep(1000);/*1秒钟刷新一次界面*/    
  100.                 sendMsg(FileUtil.updateDownloadMeg);    
  101.             }    
  102.             Log.e(TAG, "下载完成");    
  103.             completed = true;    
  104.             sendMsg(FileUtil.endDownloadMeg);    
  105.         } catch (Exception e) {    
  106.             Log.e(TAG, "multi file error  Exception  "+e.getMessage());    
  107.             e.printStackTrace();    
  108.         }    
  109.         super.run();    
  110.     }    
  111.     /**  
  112.      * 得到文件的大小  
  113.      * @return  
  114.      */    
  115.     public int getFileSize()    
  116.     {    
  117.         return this.fileSize;    
  118.     }    
  119.     /**  
  120.      * 得到已经下载的数量  
  121.      * @return  
  122.      */    
  123.     public int getDownloadSize()    
  124.     {    
  125.         return this.downloadSize;    
  126.     }    
  127.     /**  
  128.      * 获取下载百分比  
  129.      * @return  
  130.      */    
  131.     public int getDownloadPercent(){    
  132.         return this.downloadPercent;    
  133.     }    
  134.    /**  
  135.     * 获取下载速度  
  136.     * @return  
  137.     */    
  138.     public int getDownloadSpeed(){    
  139.         return this.downloadSpeed;    
  140.     }    
  141.     /**  
  142.      * 修改默认线程数  
  143.      * @param threadNum  
  144.      */    
  145.     public void setThreadNum(int threadNum){    
  146.         this.threadNum = threadNum;    
  147.     }    
  148.     /**  
  149.      * 分块下载完成的标志  
  150.      * @return  
  151.      */    
  152.     public boolean isCompleted(){    
  153.         return this.completed;    
  154.     }    
  155.     @Override    
  156.     public String toString() {    
  157.         return "MultiThreadDownload [threadNum=" + threadNum + ", fileSize="    
  158.                 + fileSize + ", UrlStr=" + UrlStr + ", ThreadNo=" + ThreadNo    
  159.                 + ", savePath=" + savePath + "]";    
  160.     }    
  161.         
  162.     /**  
  163.      * 发送消息,用户提示  
  164.      * */    
  165.     private void sendMsg(int what)    
  166.     {    
  167.         Message msg = new Message();    
  168.         msg.what = what;    
  169.         handler.sendMessage(msg);    
  170.     }   

[java] view plain copy

 print?

  1. public class FileDownloadThread extends Thread{    
  2.     private static final String TAG = "FileDownloadThread";    
  3.     /**缓冲区 */    
  4.     private static final int BUFF_SIZE = 1024;    
  5.     /**需要下载的URL*/    
  6.     private URL url;    
  7.     /**缓存的FIle*/    
  8.     private File file;    
  9.     /**开始位置*/    
  10.     private int startPosition;    
  11.     /**结束位置*/    
  12.     private int endPosition;    
  13.     /**当前位置*/    
  14.     private int curPosition;    
  15.     /**完成*/    
  16.     private boolean finished = false;    
  17.     /**已经下载多少*/    
  18.     private int downloadSize = 0;    
  19.         
  20.     /***  
  21.      * 分块文件下载,可以创建多线程模式  
  22.      * @param url   下载的URL  
  23.      * @param file  下载的文件  
  24.      * @param startPosition 开始位置  
  25.      * @param endPosition   结束位置  
  26.      */    
  27.     public FileDownloadThread(URL url, File file, int startPosition,    
  28.             int endPosition) {    
  29.         this.url = url;    
  30.         this.file = file;    
  31.         this.startPosition = startPosition;    
  32.         this.curPosition = startPosition;    
  33.         this.endPosition = endPosition;    
  34.         Log.e(TAG, toString());    
  35.     }    
  36.         
  37.     @Override    
  38.     public void run() {    
  39.         BufferedInputStream bis = null;    
  40.         RandomAccessFile rAccessFile = null;    
  41.         byte[] buf = new byte[BUFF_SIZE];    
  42.         URLConnection conn = null;    
  43.         try {    
  44.             conn = url.openConnection();    
  45.             conn.setConnectTimeout(10000);//设置超时    
  46.             conn.setReadTimeout(10000);    
  47.             conn.setAllowUserInteraction(true);    
  48.                     System.out.println(this.getName()+" startPosition "+startPosition+" endPosition "+endPosition);    
  49.                     conn.setRequestProperty("Range", "bytes="+(startPosition)+"-"+endPosition);  //取剩余未下载的    
  50.                     rAccessFile = new RandomAccessFile(file,"rwd");//读写    
  51.                      //设置从什么位置开始写入数据     
  52.                     rAccessFile.seek(startPosition);    
  53.                     bis = new BufferedInputStream(conn.getInputStream(), BUFF_SIZE);    
  54.                     while(curPosition<endPosition)  //当前位置小于结束位置  继续下载    
  55.                     {    
  56.                         int len = bis.read(buf,0,BUFF_SIZE);    
  57.                         if(len==-1)   //下载完成      
  58.                         {     
  59.                             break;    
  60.                         }    
  61.                         rAccessFile.write(buf,0,len);    
  62.                         curPosition = curPosition +len;    
  63.                         if(curPosition > endPosition)    
  64.                         {   //如果下载多了,则减去多余部分    
  65.                             System.out.println("  curPosition > endPosition  !!!!");    
  66.                             int extraLen = curPosition-endPosition;    
  67.                             downloadSize += (len-extraLen+1);    
  68.                         }else{    
  69.                             downloadSize+=len;    
  70.                         }    
  71.                     }    
  72.                     this.finished = true;  //当前阶段下载完成    
  73.             Log.e(TAG, "当前"+this.getName()+"下载完成");    
  74.         } catch (Exception e) {    
  75.             Log.e(TAG, "download error Exception "+e.getMessage());    
  76.             e.printStackTrace();    
  77.         }finally{    
  78.             //关闭流    
  79.             FileUtil.closeInputStream(bis);    
  80.             try {    
  81.                 rAccessFile.close();    
  82.             } catch (IOException e) {    
  83.                 // TODO Auto-generated catch block    
  84.                 Log.e("AccessFile", "AccessFile IOException "+e.getMessage());    
  85.             }    
  86.         }    
  87.         super.run();    
  88.     }    
  89.         
  90.     /**  
  91.      * 是否完成当前段下载完成  
  92.      * @return  
  93.      */    
  94.     public boolean isFinished() {    
  95.         return finished;    
  96.     }    
  97.     /**  
  98.      * 已经下载多少  
  99.      * @return  
  100.      */    
  101.     public int getDownloadSize() {    
  102.         return downloadSize;    
  103.     }    
  104.     
  105.     @Override    
  106.     public String toString() {    
  107.         return "FileDownloadThread [url=" + url + ", file=" + file    
  108.                 + ", startPosition=" + startPosition + ", endPosition="    
  109.                 + endPosition + ", curPosition=" + curPosition + ", finished="    
  110.                 + finished + ", downloadSize=" + downloadSize + "]";    
  111.     }    

多线程下载是分段下载,创建保存一个文件,子线程分别通过RandomAccessFile类进行写入操作。

转载:http://blog.csdn.net/chaoyu168/article/details/50971687

时间: 2024-09-08 13:57:13

android --多线程下载的相关文章

Android多线程下载

项目源码下载 https://github.com/Wang-Jun-Chao/AndroidProjects 多线程下载 原理:服务器CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源 确定每条线程下载多少数据 发送http请求至下载地址 String path = URL url = new URL(path) HttpURLConnection conn = (HttpURLConnection) url() conn()

java-为什么我写的android多线程下载程序刚开始速度很快,之后越来越慢?

问题描述 为什么我写的android多线程下载程序刚开始速度很快,之后越来越慢? 我写的多线程下载程序,用了8个线程,一次读10240byte个字节. 刚开始前几s下载速度显示可以到600多k/s 但是马上就降到个位数或十几k/s 不是网络问题,因为我用别的东西下载速度都会很快. 如果我暂停后恢复又是前几s会很快,之后速度又掉下来了. 这是为什么呢??? 如何保持java下载速度,谢谢! 还有我该如何平衡线程数与一次下载字节间的关系? 解决方案 我感觉是你开启的线程 不够多的原因 供不应求

android多线程下载3

今天跟大家一起分享下android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基本要领,我们先一起简单回顾下它的基本原理. http://blog.csdn.net/shimiso/article/details/6763664  android 多线程断点续传下载 一 http://blog.csdn.net/shimiso/article/details/6763986 

android多线程下载2

在上一集中,我们简单介绍了如何创建多任务下载,但那种还不能拿来实用,这一集我们重点通过代码为大家展示如何创建多线程断点续传下载,这在实际项目中很常用. main.xml: [html] view plaincopy <?xml version="1.0" encoding="utf-8"?>   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&

Android多线程下载示例详解

一.概述 说到Android中的文件下载,Android API中明确要求将耗时的操作放到一个子线程中执行,文件的下载无疑是需要耗费时间的,所以要将文件的下载放到子线程中执行.下面,我们一起来实现一个Android中利用多线程下载文件的小例子. 二.服务端准备 在这个小例子中我以下载有道词典为例,在网上下载有道词典的安装包,在eclipse中新建项目web,将下载的有道词典安装包放置在WebContent目录下,并将项目发布到Tomcat中,具体如下图所示 三.Android实现 1.布局 界面

android 多线程下载 显示进度 速度

http://blog.csdn.net/JianTao_Yang/article/details/8433905 功能要求:从网络下载一APK应用,显示下载速度.进度,并安装应用. 运行效果图: 工程结构图: 很简单,就一个activity,一个更新UI的线程,一个下载线程加个文件处理类 主要代码:   [java] view plaincopy /**   *多线程下载,UI更新类    *@author young   * */   public class MultiThreadDown

android多线程下载模块

<strong>使用场景</strong> apk应用内更新,其他中小文件的下载,断点续传下载等,先来看看效果图: <br/> <strong>简单方便的调用接口</strong> 调用者只要设置好下载路径.文件后缀,丢一个url即可开始下载,并且可以根据需要监听进度,例如:    FileDownloader mDownloader = FileDownloader.getInstance(getApplication()); mDownloa

android多线程下载1

想做一个下载功能,当然理想的功能要支持多任务同时下载,断点续传的功能,我想一步一步来,首先困难摆在了多任务这里 开始我的思路是在一个Service中启动下载的流操作,然后通过Service中声明一个Activity中的Handler更新UI(比如进度条...) 可是我发现在Service中声明一个Activity中的Handler是做不到的(可能只是我做不到吧,无法申请内存) 于是,我决定在Activity中直接启动线程,让其运行,调用自身的Handler来更新UI,没想到在这个下载Activi

Android版多线程下载 仿下载助手(最新)_Android

首先声明一点: 这里的多线程下载并不是指多个线程下载一个 文件,而是每个线程负责一个文件,今天给大家分享一个多线程下载的 例子.先看一下效果,点击下载开始下载,同时显示下载进度,下载完成,变成程安装,点击安装提示安装应用. 界面效果图: 线程池ThreadPoolExecutor ,先简单学习下这个线程池的使用 /** * Parameters: corePoolSize the number of threads to keep in the pool, even if they are id