多线程断点下载

Android多线程断点续传下载原理及实现 这段时间看了看工作室的工具库的下载组件,发现其存在一些问题: 1.下载核心逻辑有 bug,在暂停下载或下载失败等情况时有概率无法顺利完成下载。 2.虽然原来的设计是采用多线程断点续传的设计,但打了一下日志发现其实下载任务都是在同一个线程下串行执行,并没有起到加快下载速度的作用。 考虑到原来的代码并不复杂,因此对这部分下载组件进行了重写。这里记录一下里面的多线程断点续传功能的实现。 更多完整项... 阅读详情

多线程断点下载

  1. 多线程下载

    public class MultiThreadDownloader {
    
        private URL url;        // 目标地址
        private File file;        // 本地文件
        private long threadLen;    // 每个线程下载多少
    
        private static final int THREAD_AMOUNT = 3;                // 线程数
        private static final String DIR_PATH = "F:/Download";    // 下载目录
    
        public MultiThreadDownloader(String address) throws IOException {    
            url = new URL(address);                                                            // 记住下载地址
            file = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));        // 截取地址中的文件名, 创建本地文件
            // 创建一个临时文件路径
        }
    
        public void download() throws IOException {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3000);
    
            long totalLen = conn.getContentLength();                    // 获取文件总长度
            threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;    // 计算每个线程要下载的长度
    
            // 总长度 如果能整除 线程数, 每条线程下载的长度就是 总长度 / 线程数
            // 总长度 如果不能整除 线程数, 那么每条线程下载长度就是 总长度 / 线程数 + 1
    
            RandomAccessFile raf = new RandomAccessFile(file, "rw");    // 在本地创建一个和服务端大小相同的文件
            raf.setLength(totalLen);                                    // 设置文件的大小, 写入了若干个0
            raf.close();
    
            // 创建临时文件
    
            for (int i = 0; i < THREAD_AMOUNT; i++)        // 按照线程数循环
                new DownloadThread(i).start();            // 开启线程, 每个线程将会下载一部分数据到本地文件中
        }
    
        private class DownloadThread extends Thread {
            private int id;     // 用来标记当前线程是下载任务中的第几个线程
    
            public DownloadThread(int id) {
                this.id = id;
            }
    
            public void run() {
                // 从临时文件读取当前线程已完成的进度
    
                long start = id * threadLen;                    // 起始位置
                long end = id * threadLen + threadLen - 1;        // 结束位置
                System.out.println("线程" + id + ": " + start + "-" + end);
    
                try {
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(3000);
                    conn.setRequestProperty("Range", "bytes=" + start + "-" + end);    // 设置当前线程下载的范围(start和end都包含)
    
                    InputStream in = conn.getInputStream();                            // 获取连接的输入流, 用来读取服务端数据
                    RandomAccessFile raf = new RandomAccessFile(file, "rw");        // 随机读写文件, 用来向本地文件写出
                    raf.seek(start);                                                // 设置保存数据的位置
    
                    byte[] buffer = new byte[1024 * 100];    // 每次拷贝100KB
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);            // 从服务端读取数据, 写到本地文件
                        // 存储当前下载进度到临时文件
                    }
                    raf.close();
    
                    System.out.println("线程" + id + "下载完毕");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            new MultiThreadDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
        }
    }
  2. 断点下载

    public class BreakpointDownloader {
        private static final String DIR_PATH = "F:/Download";    // 下载目录
        private static final int THREAD_AMOUNT = 3;                // 总线程数
    
        private URL url;            // 目标下载地址
        private File dataFile;        // 本地文件
        private File tempFile;        // 用来存储每个线程下载的进度的临时文件
        private long threadLen;        // 每个线程要下载的长度
        private long totalFinish;    // 总共完成了多少
        private long totalLen;        // 服务端文件总长度
        private long begin;            // 用来记录开始下载时的时间
    
        public BreakpointDownloader(String address) throws IOException {    
            url = new URL(address);                                                            // 记住下载地址
            dataFile = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));    // 截取地址中的文件名, 创建本地文件
            tempFile = new File(dataFile.getAbsolutePath() + ".temp");                        // 在本地文件所在文件夹中创建临时文件
        }
    
        public void download() throws IOException {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3000);
    
            totalLen = conn.getContentLength();                                    // 获取服务端发送过来的文件长度
            threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;            // 计算每个线程要下载的长度
    
            if (!dataFile.exists()) {                                            // 如果本地文件不存在
                RandomAccessFile raf = new RandomAccessFile(dataFile, "rws");    // 在本地创建文件
                raf.setLength(totalLen);                                        // 设置文件的大小和服务端相同
                raf.close();
            }
    
            if (!tempFile.exists()) {                                            // 如果临时文件不存在
                RandomAccessFile raf = new RandomAccessFile(tempFile, "rws");    // 创建临时文件, 用来记录每个线程已下载多少
                for (int i = 0; i < THREAD_AMOUNT; i++)                            // 按照线程数循环
                    raf.writeLong(0);                                            // 写入每个线程的开始位置(都是从0开始)
                raf.close();
            }
    
            for (int i = 0; i < THREAD_AMOUNT; i++)    // 按照线程数循环
                new DownloadThread(i).start();        // 开启线程, 每个线程将会下载一部分数据到本地文件中
    
            begin = System.currentTimeMillis();        // 记录开始时间
        }
    
        private class DownloadThread extends Thread {
            private int id;     // 用来标记当前线程是下载任务中的第几个线程
    
            public DownloadThread(int id) {
                this.id = id;
            }
    
            public void run() {
                try {
                    RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rws");        // 用来记录下载进度的临时文件
                    tempRaf.seek(id * 8);                        // 将指针移动到当前线程的位置(每个线程写1个long值, 占8字节)
                    long threadFinish = tempRaf.readLong();        // 读取当前线程已完成了多少
                    synchronized(BreakpointDownloader.this) {    // 多个下载线程之间同步
                        totalFinish += threadFinish;            // 统计所有线程总共完成了多少
                    }
    
                    long start = id * threadLen + threadFinish;        // 计算当前线程的起始位置
                    long end = id * threadLen + threadLen - 1;        // 计算当前线程的结束位置
                    System.out.println("线程" + id + ": " + start + "-" + end);
    
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(3000);
                    conn.setRequestProperty("Range", "bytes=" + start + "-" + end);        // 设置当前线程下载的范围
    
                    InputStream in = conn.getInputStream();                                // 获取连接的输入流
                    RandomAccessFile dataRaf = new RandomAccessFile(dataFile, "rws");    // 装载数据的本地文件(可以理解为输出流)
                    dataRaf.seek(start);                                                // 设置当前线程保存数据的位置
    
                    byte[] buffer = new byte[1024 * 100];            // 每次拷贝100KB
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        dataRaf.write(buffer, 0, len);                // 从服务端读取数据, 写到本地文件
                        threadFinish += len;                        // 每次写入数据之后, 统计当前线程完成了多少
                        tempRaf.seek(id * 8);                        // 将临时文件的指针指向当前线程的位置
                        tempRaf.writeLong(threadFinish);            // 将当前线程完成了多少写入到临时文件
                        synchronized(BreakpointDownloader.this) {    // 多个下载线程之间同步
                            totalFinish += len;                        // 统计所有线程总共完成了多少
                        }
                    }
                    dataRaf.close();
                    tempRaf.close();
    
                    System.out.println("线程" + id + "下载完毕");
                    if (totalFinish == totalLen) {                    // 如果已完成长度等于服务端文件长度(代表下载完成)
                        System.out.println("下载完成, 耗时: " + (System.currentTimeMillis() - begin));
                        tempFile.delete();                            // 删除临时文件
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            new BreakpointDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
        }
    }

  • 邮箱 :charon.chui@gmail.com
  • Good Luck!
多线程下载与断点续传 1. 为什么要使用断点续传 在进行数据上传的时候可能是多线程操作,很多图像数据同时做上传或者单一的图像,如果图像比较多或者单一图像数据比较大,自然不希望失败一次或者暂停一次之后完全重传,有断点续传功能可以节省网络流量和节省用户时间,体验自然比你一次次的重传好很多。 2. 什么是断点续传 所谓断点续传,也就是要从文件已经下载的地方开始继续下载。HTTP/1.1 开始就支持了。一般断点下载时才用到 Range 和 Content-Range 实体头。 2.1什么是Range? 当用户在听一首歌的时候, 阅读详情

相关推荐

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

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!资料⬅专栏获取",

2401_85729780的博客 943

断点续传实现原理 多线程下载的原理

断点续传实现原理 可以用多线程传输实现 断点续传: 所谓的断点续传就是指:文件在传输过程式中被中断后,在重新传输时,可以从上次的断点处开始传输,这样就可节省时间。 实现关键: 在这里有两个关键点 其一是检测本地已经下载的文件长度和断点值; 其二是在服务端调整文件指针到断点处 实现方法: 我们用一个简单的方法来实现断点续传的功能.在传输文件的时候创建一个临时文件用来存放文件的断点位置 在每次发送接受...

cledwyn 2856

Android原生实现多线程断点下载

SQLite的基本使用,数据库的增删改查。 Handler的消息处理与更新UI(你也可以看我的这篇文章)。 Service(主要用于下载)的进阶与使用。 原生的json文件解析(多层嵌套)。 RandomAccessFile的基本使用,可以将文件分段。 基于HttpURLConnection的大文

永远不要停下学习的脚步。 3010

java多线程下载和断点续传

<br /><br />package reflect;<br /> <br />import java.io.FileNotFoundException;<br />import java.io.IOException;<br />import java.io.InputStream;<br />import java.io.RandomAccessFile;<br />import java.net.HttpURLConnection;<br />import java.net.MalformedURL

guo624587253的专栏 7970

FTP断点续传案例以及多线程下载的Demo

FTP断点续传案例以及多线程下载的Demo 在使用FTP的过程中,很多时候需要系统支持断点续传以及多线程下载,前段时间为了做这个功能,各种搜索,综合了一下,写了一个demo,给正在写FTP的童鞋一点启发 上代码: 文件上传下载的类: package com.shallowdream.threaddemo; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.Inpu

shallowdrink的博客 589

掌握高效多线程下载与断点续传技术

在互联网中,文件下载是指将远程服务器上的数据复制到本地存储设备的过程。传统的单线程下载方式是指在一段时间内,下载任务只使用一个连接(线程)来下载文件,即以顺序的方式一个接一个地下载文件的不同部分。

weixin_30700095的博客 832

java 多线程下载 断点_JAVA下实现多线程断点下载

多线程断点下载:顾名思义是用多线程实现的,断点是当第三方因素(断电、断网等)中断下载时,下次下载可以继续上次下载的地方下载。1、通过getContentLength可以获取要下载文件的大小,这样可以在本机上创建一个相同大小的文件用来下载。int fileLength = connection.getContentLength();2、由于是多线程,所以要给每一个线程均分分配要下载的位置。for(i...

weixin_42536863的博客 297

Windows10下RTABMAP+T265实现三维建图

win10+rtabmap+t265扫描地形

Suxiang1997的博客 3489

多线程断点下载的一个基础了解

是一种任意存取流、是处理流的一种,其对象包含一个记录指针能以任意访问的方式,程序可以跳到文件的任意位置进行读写。因而可以利用这个流,利用多线程来实现多断点下载,加快下载速度。继承于java.lang.Object类,位于java.io包下。"文件记录指针" 通常指的是一个指向文件中某个位置的指针。这个指针可以用于定位文件中的数据,以便读取或写入特定的位置。文件记录指针的概念常常与随机访问文件相关。1.本文通过仿真,了解多线程断点下载的很初级的方法和理念,能够成功复制/下载视频、文件、图片等。

2301_81434957的博客 1027

企业信息化系统的组成模块-核心业务系统

通过标准化的数据流形成完整的业务闭环,CRM生成的销售订单驱动ERP的生产和采购,ERP将生产计划传递给MES执行,MES报工数据返回ERP进行成本核算,ERP再将交付信息同步给CRM供客户查询。生产管理确保高效交付,缩短订单周期。某贸易公司实施ERP供应链模块后,库存周转率从每年4次提升到8次,库存资金占用从2000万降到1200万,释放800万现金流,同时缺货率从15%降到5%。│ │库存 │ │ MRP │ │ ERP │ │ 云ERP/ │ │。

weiyvyy的博客 697

【STM32实战】利用STM32CubeMX配置PWM互补输出驱动电机

本文详细介绍了如何利用STM32CubeMX配置STM32高级定时器的PWM互补输出功能,以驱动电机等需要半桥/全桥电路的应用。通过图形化界面设置定时器参数、使能互补通道并配置关键的死区时间,结合代码示例演示了如何启动PWM输出和动态调整占空比,确保输出安全、精确的互补信号,避免MOS管直通风险,提升驱动可靠性。

weixin_29161785的博客 536

Android文件下载——多线程断点下载

1. 前言     在前面的博客中简单实现了Android单线程断点下载以及Android文件多线程下载,这篇将实现多线程断点下载。对于断点下载,我们知道主要是为了实现不重复下载上次下载过的数据文件内容,而和前面实践的区别在于我们将从单线程环境拓展到多线程环境中。下面简单整理下思路。 2. 设计思路 确定多线程环境下的线程数量; 确定每个线程自己所需要下载的数据范围; 每个线程下载的数据,使用临时文件进行存储,最终进行文件合并。 (测试结果发现合并太耗时了,故而不考虑使用临时文件的方式。) 记录每个线程下

梦否 1834

STK中的传感器与通信组件:雷达、发射机、接收机与天线的协同建模

本文深入解析了STK软件中传感器、雷达、发射机、接收机与天线的协同建模方法。通过构建一个完整的卫星对地数传系统实例,阐述了各组件如何分工协作,实现从几何指向到射频链路的高保真仿真,为复杂航天通信与探测系统的设计与分析提供了高效、灵活的解决方案。

weixin_29271263的博客 273

后台多任务多线程断点下载

多线程断点下载其实不是很难,主要就是三个方面: 1、根据文件的大小和下载线程的数量,确定每个下载线程要下载的分割文件的大小; 2、记录每个下载线程已经下载完成的进度; 3、将每个线程下载的分割的文件合并到一个文件中。 那么怎么将远程的一个文件分割成三部分来下载呢?其实在HTTP协议中,有一个Range字段,用于客户端到服务器端的请求,可通过该字段指定下载文件的某一段大小,及其单位,格式为:

林静月下的博客 2711

实战解析:利用Python requests库高效抓取京东商品评论并构建结构化数据集

本文详细介绍了如何利用Python requests库高效抓取京东商品评论并构建结构化数据集。通过分析京东评论接口、处理反爬机制以及数据解析存储,帮助开发者快速获取电商数据,适用于竞品监控、用户画像构建等商业场景。

weixin_42526415的博客 838

YOLOv8改进策略【卷积层】| DEConv: 强度信息与梯度特征融合的细节增强 适用于小目标与细节目标检测任务

本文记录的是利用 模块优化 的目标检测网络模型。(Detail-Enhanced Convolution,细节增强卷积)的设计旨在,解决 目标检测网络中传统普通卷积缺乏目标细节相关先验、对小目标边缘、目标与背景边界等关键细节捕捉能力不足的问题,同时避免引入额外参数量与计算开销,以适配 对实时推理性能与检测精度的双重需求。DEA-Net: Single image dehazing based on detail-enhanced convolution and content-guided atte

Limiiiing的博客 349

Android之—多线程断点续传下载

Android之——多线程断点续传下载示例 文件下载在App应用中也用到很多,一般版本更新时多要用的文件下载来进行处理,以前也有看过很多大神有过该方面的博客,今天我也自己来实践一下,写的一般,还请大家多提意见,共同进步。主要思路: 1.多线程下载: 首先通过下载总线程数来划分文件的下载区域:利用int range = fileSize / threadCount;得到每一段下载量;每

qingxuan521721的博客 606

A2B V1.0协议学习笔记(A2B System Specification V1.0)

A2B全称是 Automotive Audio Bus 汽车音频总线,主要是解决传统音频总线线多、线重、成本贵等问题。本文是以A2B V1.0规范为准,现在ADI又推出了A2B V2.0,物理层不兼容,采用了QPSK编码方式,后续有时间再更新。A2B总线的优点:支持1主多从的架构(最多10个子节点)支持50Mbps(具体是49.152 Mbps)的高带宽传输以及

qflook的博客 4428

java 多线程下载 断点_Java多线程断点下载

1 importjava.io.File;2 importjava.io.FileInputStream;3 importjava.io.InputStream;4 importjava.io.RandomAccessFile;5 importjava.net.HttpURLConnection;6 importjava.net.URL;78 /**9 * 多线程断点下载示例10 *@author...

weixin_36181191的博客 132

linux v3h平台开发系列详解(GMSL摄像头篇):1.12 解串器MAX96712输出4 lane 变 2 lane的配置

本文详细介绍了在Linux v3h平台上,针对Max96712解串器进行MIPI 4lane到2lane配置。内容包括串行器解串器介绍、链路框架、硬件连接、以及软件寄存器如何配值和一些问题的解决方法。

xian18809311584的博客 1095

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Android实现多线程断点续传下载

前言 我们常常在开发过程中会遇到下载的功能实现,当我们下载中断时,又不希望下次从头开始继续下载,我们就需要用到断点续传了。 断点续传原理 断点续传是指当下载中断后,再次下载时可以从上次的下载进度继续下载。由此我们可以分析得出实现这个功能,我们需要实时保存下载进度,这样在下次继续下载的时候再把下载进度读取出来,继续下载。我们主要需要解决俩个问题:一、从上次的位置继续下载。二、从上次写入的文...

allbule的博客 471

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

android多线程断点,Android使用多线程实现断点下载

多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务..可以使任务的执行速度变快..多线程的任务下载时常都会使用得到..比如说我们手机内部应用宝的下载机制..一定是通过使用了多线程创建的下载器..并且这个下载器可以实现断点下载..在任务被强行终止之后..下次可以通过触发按钮来完成断点下载...那么如何实现断点下载这就是一个问题了..首先我们需要明确一点就是多线程下载器通过使用多个线程...

weixin_34122532的博客 382

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

java多线程断点下载

java多线程断点下载 solary2016 关注 2016.10.14 17:21* 字数 863 阅读 288评论 0喜欢 6最近闲的比较蛋疼,原本软件计划招20个人的,现在14个人的团队都是一半在打酱油,这跟全国经济形势有关,我们也没太大办法,所以最近是啥都看看。昨天晚上看了一个多线程断点下载...

daimengs的博客 373

java 多线程下载 断点_Java实现多线程断点下载

导读热词JAVA多线程断点下载原理如图:代码如下:import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.RandomAccessFile;im...

weixin_31458015的博客 279

Android_Service多线程断点下载

Android中实现单线程下载文件是比较容易的,可是要使得自己的应用支持多线程断点下载就要考虑到很多细节了,今天我们一起来探讨一下多线程断点下载时怎么实现的。 首先先画一张图说明一下Android中下载文件的大致流程: 上面的图介绍的是比较清楚的,我们要下载一个文件,首先需要在Activity中选择需要下载的目标,然后把下载的任务交个Service中(这里为什么要交给Service

gjnm820的博客 1948
上一篇: 代码混淆
下一篇: 短信广播接收者
CharonChui
博客等级 码龄12年 66粉丝 134原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值