当前位置: 首页 > news >正文

Android 断点续传进阶之多线程下载

今天继续下载的风骚走位内容—多线程多文件断点续传

Android 断点续传基础之单线程下载:http://blog.csdn.net/qq_27489007/article/details/53897653

效果图:

文件关系:

所需内容

多文件下载列表的显示

启动多个线程分段下载

使用通知栏显示进度条

使用其他方式实现线程通信

与单线程不主要不同:

任务下载类(DuoDownloadTask) 使用了线程池, 数据库对线程的增、删操作使用synchronized

多线程下载原理简介

假设要分3个线程下载一个100字节的文件,每个线程可以平分线程1(0-32字节)、 线程2(33-65字节)、线程3(66-100字节)

部分主要代码:

/**

  • 多线程多文件的下载任务类,为了学习查看方便 所以提出来了

  • Created by lung on 2016-12-17.

*/

public class DuoDownloadTask {

private Context mContext = null;

private FileInfo mFileInfo = null;

private ThreadDAOImpl mThreadDAO = null;

private long mFinished = 0; //总的完成进度

public boolean isPause = false; //暂停下载的开关

private int mThreadCount = 1; //线程数量

private List downloadThreadList = null;//线程集合 方便管理

public static ExecutorService executorService = Executors.newCachedThreadPool();//线程池

public DuoDownloadTask(Context mContext, FileInfo mFileInfo, int mThreadCount) {

this.mContext = mContext;

this.mFileInfo = mFileInfo;

this.mThreadCount = mThreadCount;

mThreadDAO = new ThreadDAOImpl(mContext);

}

//下载的方法

public void download() {

//读取数据库的线程信息

List threaddInfos = mThreadDAO.getThreads(mFileInfo.getUrl());

if (threaddInfos.size() == 0) { //如果数据库无线程信息

//获得每个线程下载的长度

int length = mFileInfo.getLength() / mThreadCount;

for (int i = 0; i < mThreadCount; i++) {

// 参数三线程开始的地方 参数四 线程结束的地方 参数五任务完成的进度

TheardInfo theardInfo = new TheardInfo(i, mFileInfo.getUrl(), length * i, (i + 1) * length - 1, 0);

//最后一个线程 会出现除不尽的情况

if (i == mThreadCount - 1) {

//直接把线程的结束位置 设置成文件的最大长度位置

theardInfo.setEnd(mFileInfo.getLength());

}

//添加到线程信息集合中

threaddInfos.add(theardInfo);

//向数据库插入线程信息

mThreadDAO.insertThread(theardInfo);

}

}

downloadThreadList = new ArrayList<>();

//启动多个线程进行下载

for (TheardInfo info : threaddInfos) {

DownloadThread thread = new DownloadThread(info);

// thread.start(); //开始线程添加到集合中

DuoDownloadTask.executorService.execute(thread); //利用线程池来执行线程任务

downloadThreadList.add(thread); //把线程添加进去方便ckeckAllThreadFinshed检查线程

}

}

//这个方法 用来判断所有的线程是否都执行完了

private synchronized void checkAllThreadFinshed() {

boolean allFinished = true;

//遍历线程集合,判断线程是否都执行完毕

for (DownloadThread thread : downloadThreadList) {

if (!thread.isFinished) {

allFinished = false;

break;

}

}

if (allFinished) { //如果线程都完成了

//下载完成后 删除线程信息

//删除下载记录

mThreadDAO.deleteThread(mFileInfo.getUrl(), mFileInfo.getId());

//发送广播通知ui下载任务结束

Intent intent = new Intent(DuoDownloadService.ACTION_FINISHED);

intent.putExtra(“fileInfo”, mFileInfo);

mContext.sendBroadcast(intent); //发送广播

}

}

class DownloadThread extends Thread {

private TheardInfo threadInfo;

public boolean isFinished = false; //用来标识线程是否结束

public DownloadThread(TheardInfo threadInfo) {

this.threadInfo = threadInfo;

}

@Override

public void run() {

//设置下载位置

try {

URL url = new URL(threadInfo.getUrl());

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod(“GET”);

conn.setConnectTimeout(3000);

//开始的字节数 为开始加上完成的长度

long start = threadInfo.getStart() + threadInfo.getFinished();

//下载的范围 开始的字节数 到结束的字节数

conn.setRequestProperty(“Range”, “bytes=” + start + “-” + threadInfo.getEnd());

//设置文件写入位置 路径 文件名

File file = new File(DownloadService.DOWNLOAD_PATH, mFileInfo.getFileName());

//

RandomAccessFile raf = new RandomAccessFile(file, “rwd”);

raf.seek(start); //文件的写入位置

Intent intent = new Intent(DownloadService.ACTION_UPDATE);//把进度广播发送给activity 所以需要intent

mFinished += threadInfo.getFinished();//从线程中拿到完成的进度

//开始下载

if (conn.getResponseCode() == 206) {

//读取数据

InputStream input = conn.getInputStream();

byte[] buffer = new byte[1024 * 4];

int len = -1;

long time = System.currentTimeMillis(); //拿到当前时间

while ((len = input.read(buffer)) != -1) {

//写入文件

raf.write(buffer, 0, len);

//把下载进度发送广播给activity

mFinished += len; //把现在下载的进度累加进去

//累加每个线程完成的进度

threadInfo.setFinished(threadInfo.getFinished() + len);

if (System.currentTimeMillis() - time > 1000) { //减少ni负载 大于10秒发送更新

time = System.currentTimeMillis();

//以百分比的形式发送给广播

intent.putExtra(“finished”, (int) (mFinished * 100 / mFileInfo.getLengt
h()));

intent.putExtra(“id”, mFileInfo.getId());

mContext.sendBroadcast(intent);

}

//在下载暂停时,保存下载进度

if (isPause) { //如果暂停 把线程信息进行保存 最后一个参数 他会把每个线程的 进度保存起来

mThreadDAO.updateThread(mFileInfo.getUrl(), mFileInfo.getId(), threadInfo.getFinished());

return;

}

}

intent.putExtra(“finished”, 100);

mContext.sendBroadcast(intent); //发送广播

// 标识线程执行完毕

isFinished = true;

//每个线程执行完毕 都执行去判断 所有的线程是否都执行完毕

checkAllThreadFinshed();

input.close();

}

raf.close();

conn.disconnect();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally { //关闭各种链接

}

super.run();

}

}

}

ThreadDAOImpl.java

相关文章:

Android 断点续传进阶之多线程下载

今天继续下载的风骚走位内容—多线程多文件断点续传 Android 断点续传基础之单线程下载&#xff1a;http://blog.csdn.net/qq_27489007/article/details/53897653 效果图&#xff1a; 文件关系&#xff1a; 所需内容 多文件下载列表的显示 启动多个线程分段下载 使用通知栏…...

Python爬虫学习 | Scrapy框架详解

一.Scrapy框架简介 何为框架&#xff0c;就相当于一个封装了很多功能的结构体&#xff0c;它帮我们把主要的结构给搭建好了&#xff0c;我们只需往骨架里添加内容就行。scrapy框架是一个为了爬取网站数据&#xff0c;提取数据的框架&#xff0c;我们熟知爬虫总共有四大部分&am…...

用户态协议栈05—架构优化

优化部分 添加了in和out两个环形缓冲区&#xff0c;收到数据包后添加到in队列&#xff1b;经过消费者线程处理之后&#xff0c;将需要发送的数据包添加到out队列。添加数据包解析线程&#xff08;消费者线程&#xff09;&#xff0c;架构分层 #include <rte_eal.h> #inc…...

模拟退火算法

模拟退火算法&#xff08;Simulated Annealing, SA&#xff09;是一种用于全局优化问题的概率搜索算法&#xff0c;其灵感来自于金属退火过程。在金属退火中&#xff0c;材料被加热到高温&#xff0c;然后缓慢冷却&#xff0c;以减少其晶格中的缺陷并达到最小能量状态。模拟退火…...

Java匿名类

Java 匿名类是一种特殊的内部类&#xff0c;它没有名字&#xff0c;并且通常用来简化代码实现&#xff0c;尤其是在实现接口或者抽象类的实例时。匿名类可以在实例化时定义其行为&#xff0c;而不需要创建单独的类文件。 匿名类的特点 没有名字&#xff1a;匿名类是没有名字的…...

G7易流赋能化工物流,实现安全、环保与效率的共赢

近日&#xff0c;中国物流与采购联合会在古都西安举办了备受瞩目的第七届化工物流安全环保发展论坛。以"坚守安全底线&#xff0c;追求绿色发展&#xff0c;智能规划化工物流未来"为主题&#xff0c;该论坛吸引了众多政府部门、行业专家和企业代表的参与。G7易流作为…...

y=sin(2x)

函数 \( y \sin(2x) \) 是一个正弦函数&#xff0c;其中 \( x \) 是自变量&#xff0c;\( y \) 是因变量。这个函数描述了一个周期性波动的波形&#xff0c;其特点是&#xff1a; 1. **振幅**&#xff1a;正弦函数的振幅是 1&#xff0c;这意味着波形在 \( y \) 轴上的最大值…...

快捷方式(lnk)--加载HTA-CS上线

免责声明:本文仅做技术交流与学习... 目录 CS: HTA文档 文件托管 借助mshta.exe突破 本地生成lnk快捷方式: 非系统图标路径不同问题: 关于lnk的上线问题: CS: HTA文档 配置监听器 有效载荷---->HTA文档--->选择监听器--->选择powershell模式----> 默认生成一…...

从同—视角理解扩散模型(Understanding Diffusion Models A Unified Perspective)

从同—视角理解扩散模型 Understanding Diffusion Models A Unified Perspective【全公式推导】【免费视频讲解】 B站视频讲解 视频的论文笔记 从同一视角理解扩散模型【视频讲解笔记】 配合视频讲解的同步笔记。 整个系列完整的论文笔记内容如下&#xff0c;仅为了不用—一回复…...

docker 基本用法及跨平台使用

一、Docker的优点 docker 主要解决的问题就是程序开发过程中编译和部署中遇到的环境配置的问题。 1.1 Docker与其他虚拟机层次结构的区别** 运行程序重点关注点在于环境。 VM虚拟机是基于Hypervisor虚拟化服务运行的。 Docker是基于内核的虚拟化技术实现的。 1.2 Docker的技…...

Vscode远程ubuntu

远程连接 到这里vscode远程到ubuntu和关闭远程连接&#xff0c;已完成 配置python环境 在远程目录下新建.vscode隐藏文件夹&#xff0c;文件夹里新建一个 settings.json 文件&#xff0c; 先远程服务器看下conda下的python虚拟环境位置 settings.json位置及内容如下 测试pyt…...

SHA256 安全散列算法加速器实验

1、SHA256 介绍 SHA256 加速器是用来计算 SHA-256 的计算单元&#xff0c; SHA256 是 SHA-2 下细分出的一种算法。 SHA-2 名称来自于安全散列算法 2 &#xff08;英语&#xff1a; Secure Hash Algorithm 2 &#xff09;的缩写&#xff0c;一种密码散列函 数算法标准…...

Elasticsearch-ES查询单字段去重

ES 语句 整体数据 GET wkl_test/_search {"query": {"match_all": {}} }结果&#xff1a; {"took" : 123,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0…...

【Apache Doris】周FAQ集锦:第 7 期

【Apache Doris】周FAQ集锦&#xff1a;第 7 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…...

EE trade:炒伦敦金的注意事项及交易指南

在贵金属市场中&#xff0c;伦敦金因其高流动性和全球认可度&#xff0c;成为广大投资者的首选。然而&#xff0c;在炒伦敦金的过程中&#xff0c;投资者需要注意一些关键点。南华金业小编带您一起来看看。 国际黄金报价 一般国际黄金报价会提供三个价格&#xff1a; 买价(B…...

JAVA医院绩效考核系统源码 功能特点:大型医院绩效考核系统源码

JAVA医院绩效考核系统源码 功能特点&#xff1a;大型医院绩效考核系统源码 医院绩效管理系统主要用于对科室和岗位的工作量、工作质量、服务质量进行全面考核&#xff0c;并对科室绩效工资和岗位绩效工资进行核算的系统。医院绩效管理系统开发主要用到的管理工具有RBRVS、DRGS…...

Python神经影像数据的处理和分析库之nipy使用详解

概要 神经影像学(Neuroimaging)是神经科学中一个重要的分支,主要研究通过影像技术获取和分析大脑结构和功能的信息。nipy(Neuroimaging in Python)是一个强大的 Python 库,专门用于神经影像数据的处理和分析。nipy 提供了一系列工具和方法,帮助研究人员高效地处理神经影…...

非关系型数据库NoSQL数据层解决方案 之 Mongodb 简介 下载安装 springboot整合与读写操作

MongoDB 简介 MongoDB是一个开源的面向文档的NoSQL数据库&#xff0c;它采用了分布式文件存储的数据结构&#xff0c;是当前非常流行的数据库之一。 以下是MongoDB的主要特点和优势&#xff1a; 面向文档的存储&#xff1a; MongoDB是一个面向文档的数据库管理系统&#xff0…...

使用Redis优化Java应用的性能

使用Redis优化Java应用的性能 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨如何使用Redis优化Java应用的性能。Redis是一种开源的内存数据结构…...

基于Python的数据可视化大屏的设计与实现

基于Python的数据可视化大屏的设计与实现 Design and Implementation of Python-based Data Visualization Dashboard 完整下载链接:基于Python的数据可视化大屏的设计与实现 文章目录 基于Python的数据可视化大屏的设计与实现摘要第一章 导论1.1 研究背景1.2 研究目的1.3 研…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

Java数组Arrays操作全攻略

Arrays类的概述 Java中的Arrays类位于java.util包中&#xff0c;提供了一系列静态方法用于操作数组&#xff08;如排序、搜索、填充、比较等&#xff09;。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序&#xff08;sort&#xff09; 对数组进行升序…...