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. Js 希望某链接只能点击一次

    <a onclick=”function(){...}”> 希望这连接只能执行一次 <a onclick=”function(){...}; this.onclick()=funct ...

  2. HDU-3315 My Brute

    先对于每种可能的PK情况进行判断胜负,然后求最小改动最大匹配. #include <cstdlib> #include <cstdio> #include <cstrin ...

  3. Python Base One

    //this is my first day to study python, in order to review, every day i will make notes (2016/7/31) ...

  4. Java如何获取ISO 8601时间

    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); df.setTimeZone(TimeZ ...

  5. 你所在的公司是如何实施DEVOPS的?

    工欲善其事,必先利其器,现在大家在DevOps领域最关注的还是在工具层面.下面是我跟这么多公司接触下来,大家使用比较多的工具:1.监控工具比较老牌的就是Zabbix,Nagios,用Zabbix的感觉 ...

  6. Codeforces663E. Binary Table

    $n \leq 20,m \leq 100000$的01矩阵,可整行整列01翻转,问最少剩几个1. 一个暴力的做法是枚举$2^n$种行翻转然后$m$列扫一遍.但其实在行翻转情况确定的情况下我们只关心两 ...

  7. input弹出的手机键盘搜索事件

    一.input的搜索框    在input标签里面把type设置为search就可以了.弹出的手机键盘回车键也会变成搜索或者是搜索的图标. <input id="search" ...

  8. Perl语言入门--2--perl的运算符

    一.算数运算符 **:是幂 结果不能超过数的范围 当指数为小数时 底数不能为负数 %:取余数  两边的操作数为整数,如果不是则要截取,把所有的小数部分去掉 注意:当一个字符串参加运算,需要转化为整数时 ...

  9. php接口开发时,数据解析失败问题,字符转义,编码问题

    php接口开发时,数据解析失败问题,字符转义,编码问题 情景: A平台--->向接口请求数据---->接口向B平台请求数据---->B平台返回数据给接口---->接口返回数据给 ...

  10. java 判断请求来自手机端还是电脑端

    根据当前请求的特征,判断该请求是否来自手机终端,主要检测特殊的头信息,以及user-Agent这个header public static boolean isMobileDevice(HttpSer ...