1、多线程介绍

用过迅雷的同学都知道。迅雷有个功能叫做多线程。另一个叫离线下载,我们这里重点介绍一下多线程下载。多线程,顾名思义就是非常多歌线程同一时候在执行,为什么要提出多线程这个概念呢?由于有时候一个线程下载太慢了。举个样例,比方小时候常做的数学题,一个人挖沟须要15天,那么两个人对着挖呢?

当然数学题上面两个人的效率是不一样的,我们这里把这个问题简化了一下。仅仅是想大家明确,什么是多线程,为什么有多线程。

在多线程上出现过一个问题,为什么有要提出多线程?事实上提出多线程是为了充分利用CPU的硬件资源,解决应用程序等待的问题。多线程是为了同步完毕多项任务,不是为了提高执行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间须要完毕多项任务的时候实现的。

2、思路

(1)获取网络连接

(2)初始化多线程下载信息,開始下载

(3)开辟硬盘空间,用于存放数据资源

(4)把从网络获取的数据放入申请的空间中

(5)完成下载,关闭资源链接

给出一个下载400M电影的示意图,例如以下所看到的:

RandomAccessFile支持随机的訪问

HTTP的Range头字段指定每一个线程从文件的什么位置開始下载。

3、代码解析

3.1 设置须要下载文件的信息

RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rwd");
if(this.fileSize>0){
randOut.setLength(this.fileSize);//设置文件的大小
}
randOut.close(); //关闭该文件,使设置生效

3.2 设置下载链接,而且開始划分下载部分

URL url = new URL(this.downloadUrl);
if(this.data.size() != this.threads.length){ //假设原先未曾下载或者原先的下载线程数与如今的线程数不一致
this.data.clear(); //将数据置空
for (int i = 0; i < this.threads.length; i++) { //遍历线程池
this.data.put(i+1, 0);//初始化每条线程已经下载的数据长度为0
}
this.downloadedSize = 0; //设置已经下载的长度为0
}

3.3 開始下载文件

for (int i = 0; i < this.threads.length; i++) {
//通过特定的线程ID获取该线程已经下载的数据长度
int downloadedLength = this.data.get(i+1);
//推断线程是否已经完毕下载,否则继续下载
if(downloadedLength < this.block && this.downloadedSize < this.fileSize){
//初始化特定id的线程
this.threads[i] = new DownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
//设置线程的优先级,Thread.NORM_PRIORITY = 5 Thread.MIN_PRIORITY = 1 Thread.MAX_PRIORITY = 10
this.threads[i].setPriority(7);
//启动线程
this.threads[i].start();
}else{
this.threads[i] = null; //表明在线程已经完毕下载任务
}
}

3.4 监听文件是否下载完毕以及完毕之后的操作

fileService.delete(this.downloadUrl);	//假设存在下载记录,删除它们。然后又一次加入
fileService.save(this.downloadUrl, this.data); //把已经下载的实时数据写入数据库

boolean notFinished = true;//下载未完毕
// 循环推断所有线程是否完毕下载
while (notFinished) {
notFinished = false;//假定所有线程下载完毕
for (int i = 0; i < this.threads.length; i++){
if (this.threads[i] != null && !this.threads[i].isFinished()) {//假设发现线程未完毕下载
notFinished = true;//设置标志为下载没有完毕
//假设下载失败,再又一次在已经下载的数据长度的基础上下载
if(this.threads[i].getDownloadedLength() == -1){
//又一次开辟下载线程。代码与上面一致
}
}
}
if(listener!=null){
listener.onDownloadSize(this.downloadedSize);
}//通知眼下已经下载完毕的数据长度
} //下载完毕删除记录
if(downloadedSize == this.fileSize){
fileService.delete(this.downloadUrl);
}

4、断点续传

断点续传是说在下载的时候,我们由于某些原因,导致了下载的暂停。比方在电脑上,我们的电脑突然断电了,手机上的网络中断了,都会导致当前的下载任务终止,那么当我们再次回来的时候。程序应该是能够继续下载的,不然前面下载的资源就都浪费了。

依据上面的描写叙述。我们应该能够知道。实现断点续传,关键是实现下载的数据存储在数据库中,等到之后我们程序再次进入的时候,会到数据库中去查询一下数据。然后接着继续下载。

而存储数据到数据库并非太复杂,难的是怎样识别程序的哪些数据被下载了。哪些数据是没有下载的。这里,我们在下载的时候使用了下载的线程id做识别。

        假设该线程id的数据没有被完整下载。应该是不会存储到数据库的,那么这一部分的数据就要又一次下载,在下载完毕之后,数据拼接起来就是一个完整的文件了。

Android多线程下载大文件解析的更多相关文章

  1. Android 开发工具类 27_多线程下载大文件

    多线程下载大文件时序图 FileDownloader.java package com.wangjialin.internet.service.downloader; import java.io.F ...

  2. Andoid 更好的Android多线程下载框架

    概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...

  3. 更好的Android多线程下载框架

    /** * 作者:Pich * 原文链接:http://me.woblog.cn/ * QQ群:129961195 * Github:https://github.com/lifengsofts */ ...

  4. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

    1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  5. android程序---->android多线程下载(一)

    多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...

  6. android程序---->android多线程下载(二)

    上篇我们讲到了android中下载的断点续传问题,今天我们开始学习下载的多线程问题.本次的多线程源码下载:androdi中多线程下载的实现代码.有关断点续传的问题,请参见博客:android程序--- ...

  7. 转(Response.WriteFile 无法下载大文件解决方法)

    以前用Response.WriteFile(filename),但当遇到大文件时无法完整下载. 该方法最大的问题,它不是直接将数据抛到客户端,而是在服务器端(IIS)上缓存.当下载文件比较大时,服务器 ...

  8. JAVA多线程下载网络文件

    JAVA多线程下载网络文件,开启多个线程,同时下载网络文件.   源码如下:(点击下载 MultiThreadDownload.java) import java.io.InputStream; im ...

  9. python下载大文件

    1. wget def download_big_file_with_wget(url, target_file_name): """ 使用wget下载大文件 Note: ...

随机推荐

  1. 关于php ‘==’ 与 '===' 遇见的坑

    两个的区别所有PHPer都知道, 今天在遍历 xmlNode时,自己写的代码就碰坑了 想遍历xmlNode为数组 得到的xmlNode为 想要把所有的simpleXmlElement对象都遍历转成数组 ...

  2. iOS------手势操作(nib文件、纯代码)

    总共有六种手势识别:轻击手势(TapGestureRecognizer),轻扫手势 (SwipeGestureRecognizer), 长按手势(LongPressGestureRecognizer) ...

  3. Github与Eclipse连接(方法2成功:Pleiades)

    2018-3-7 第1次尝试 主要参考这位大神的笔记:http://blog.csdn.net/zhangdaiscott/article/details/16939165 方法非常简单,从官网htt ...

  4. 【CF1027A】Palindromic Twist(模拟)

    题意:输入T组字符串,每个字符串都必须改变一次,每个字母改变的规则是变成相邻的字母,字母a只能变b,z只能变y,判断改变后的字符依旧是否能够变成回文串 n<=1e2 思路: #include&l ...

  5. CodeforcesD. Aztec Catacombs

    $n \leq 300000$的完全无向图,每条边有可行和不可行的状态,一开始只有$m \leq 300000$条边是可行的,给出.每次从$x$走到$y$时,所有与$x$相连的边的可行/不可行状态会改 ...

  6. ListView列表刷新方法的区别

    ListView列表刷新方法的区别 ListView对象的刷新方法: listNote.invalidate();重绘所有组件listNote.invalidateViews();重绘组件[包含所有的 ...

  7. 26深入理解C指针之---不规则数组与指针

    一.不规则数组:每一行的列数不相等 1.复合字面量: 1).复合字面量是一种C构造 2).外形和数组声明差不多,写法与类型转换一样,(int[3]){10, 20, 30,} 3).将多个复合字面量可 ...

  8. 22深入理解C指针之---通过指针传递函数

    一.通过指针传递函数与通过指针传递数据的本质是一样的,区别就是此时的数据是函数指针(函数的开始的地址) 1.定义:通过函数指针将函数传入函数:通过函数返回函数指针实现函数返回函数的目标 2.特征: 1 ...

  9. js 克隆数据 (数组的深浅拷贝)

    var a1 = [1,2,3]; var a2 = a1; a2[0] = 90; console.log(a1[0]) //90 解析:数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结 ...

  10. chartcontrol(统计坐标图形控件)

    统计图形 把控件拖放到界面会弹出下图 图形共分八系列:Bar Series,Point and line Series,pie Series,Funnel Series,Area  Series,Ra ...