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. Apache2 FastCGI C Demo

    安装依赖 sudo apt-get install libapache2-mod-fastcgi a2enmod fastcgi sudo apt-get install libfcgi-dev li ...

  2. 解决 Jackson反序列化 Unexpected token ... , expected VALUE_STRING: need JSON String that contains type id (for subtype of ...)

    首先检查是否是 objectMapper.enableDefaultTyping(); 的受害者.优先考虑删除该配置. 使用Jackson把数组的json字符串反序列化为List时候报了个JsonMa ...

  3. brk(), sbrk() 用法详解【转】

    转自:http://blog.csdn.net/sgbfblog/article/details/7772153 贴上原文地址,好不容易找到了:brk(), sbrk() -- 改变数据段长度 brk ...

  4. Day 21 三元表达式、生成器函数、列表解析

    知识点程序: #! /usr/bin/env python # -*- coding: utf-8 -*- # __author__ = "DaChao" # Date: 2017 ...

  5. ubuntu下打开windows里的txt文件乱码解决

    是编码问题引起的问题: Linux下默认的编码是UTF-8,而Windows下默认的编码是GB2312/GBK.执行如下第一条语句即可 gsettings set org.gnome.gedit.pr ...

  6. Failed to check the status of the service报错解决

    报这个错误是因为我的application_context.service.xml 文件里的的dubbo声明暴露口时的ref属性写错了. <dubbo:service interface=&qu ...

  7. eclipse 五种断点

    1. Line BreakpointLine Breakpoin是最简单的Eclipse断点,只要双击某行代码对应的左侧栏,就对该行设置上断点. 2. WatchpointLine Breakpoin ...

  8. jsonp _____跨域请求实现

    请求如下: $.ajax({ type: "GET", async:false, url: "http://127.0.0.1:8080/Cross-site-reque ...

  9. maven命令行创建project

    创建普通java project: mvn archetype:generate -DgroupId=com.vincent -DartifactId=Java_Project -DpackageNa ...

  10. Css实现一个菜单导航

    提要:使用大div定位设置为relative,子div设置为absolute实现菜单下拉 实现代码: <!DOCTYPE html> <html lang="en" ...