多线程下载

系统运
• 阅读 3052

原理

多线程下载的原理就是将要下载的文件分成若干份,其中每份都使用一个单独的线程进行下载,这样对于文件的下载速度自然就提高了许多。

既然要分成若干部分分工下载,自然要知道各个线程自己要下载的起始位置,与要下载的大小。所以我们要解决线程的分配与各个线程定位到下载的位置。

封装

对于多线程下载我们可以将其封装到一个工具类中DownUtil,向其中传入下载的链接、文件存储路径、需要下载的线程数

public DownUtil(String path, String targetFile, int threadNum) {
        this.path = path;
        this.targetFile = targetFile;
        this.threadNum = threadNum;
        downThreads = new DownThread[threadNum];
    }

其中DownThread实现的是各个线程的下载

分配线程

这里通过HttpURLConnection进行网络请求下载,通过getContentLength()方法获取下载文件的总大小,再对其平均分配各个线程需要下载的大小。这样就确定了下载的大小,下面就是定位到各个线程的开始位置进行下载,这里可以使用RandomAccessFile来追踪定位到要下载的位置,它的seek()方法可以进行定位。下面是详细代码:

    public void download() throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setRequestProperty("Accept-Language", "zh-CN");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Connection", "Keep-Alive");

        fileSize = conn.getContentLength();
        conn.disconnect();
        //需要下载的大小
        int currentPartSize = fileSize / threadNum + 1;
        RandomAccessFile file = new RandomAccessFile(targetFile, "rw");

        //设置本地文件大小
        file.setLength(fileSize);
        file.close();
        for (int i = 0; i < threadNum; i++) {
            //下载开始位置
            int startPos = i * currentPartSize;
            RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw");
            //定位到下载位置
            currentPart.seek(startPos);
            //下载线程
            downThreads[i] = new DownThread(startPos, currentPartSize, currentPart);
            downThreads[i].start();
        }
    }

线程下载

下面就是各个线程的下载DownThread,上面已经得到了各个线程要下载的初始位置,所以可以通过获取网络请求的输入流InputStream,通过skip()方法跳跃到指定位置进行读取数据,再写入到RandomAccessFile文件中。

        public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
            this.startPos = startPos;
            this.currentPartSize = currentPartSize;
            this.currentPart = currentPart;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                conn.setRequestProperty("Accept-Language", "zh-CN");
                conn.setRequestProperty("Charset", "UTF-8");
                InputStream in = conn.getInputStream();
                
                skipFully(in, startPos);
                byte[] buffer = new byte[1024];
                int hasRead = 0;
                while ((hasRead = in.read(buffer)) > 0 && length < currentPartSize) {
                    currentPart.write(buffer, 0, hasRead);
                    length += hasRead;
                }
                currentPart.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

这样就完成了一个简单的多线程的下载,最后调用封装类DownUtil就可以进行多线程下载。

总结

多线程的关键就是分配好需要下载的进程,定位进程下载的准确位置,获取输入流读取数据,同时写入到文件的相应位置。可以借助RandomAccessFile来进行定位。

当然也并非开的线程数越多下载的速度也就越快,因为线程越多对于程序处理这些线程也是一种负担,过多的话反而会降低下载的速度,所以要合理运用。

个人blog地址:https://idisfkj.github.io/arc...

关注

多线程下载

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
4年前
vue+axios下载pdf文件流
项目中用到流文件下载的需求,之前使用的方法一直都没问题,但是这次就是下载不下来,查了多种方法终于解决了,方式如下://下载文件downLoadFile(e){letide.target.dataset.id;letnamee.target.dataset.name;
Wesley13 Wesley13
4年前
java+web+批量下载文件
JavaWeb文件下载功能文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端,所以文件下载需要IO技术将服务器端的文件读取到,然后写到response缓冲区中,然后再下载到个人客户端。1\.文件名接受前端发来的文件名获取到前端页面发送过来的要下载的文件的名字StringfilenameValuereq.getP
Stella981 Stella981
4年前
C# Aspose.Cells导出xlsx格式Excel,打开文件报“Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃”
报错信息:最近打开下载的Excel,会报如下错误。(xls格式不受影响)!(https://oscimg.oschina.net/oscnet/2b6f0c8d7f97368d095d9f0c96bcb36d410.png)!(https://oscimg.oschina.net/oscnet/fe1a8000d00cec3c
Wesley13 Wesley13
4年前
IOS多线程
一、多线程每一个iOS应用程序中都有一个主线程用来更新UI界面、处理用户的触摸事件、解析网络下载的数据,因此不能把一些太耗时的操作(比如网络下载数据)放在主线程中执行,不然会造成主线程堵塞(出现界面卡死,防止界面假死),带来极坏的用户体验。iOS的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程异步编程是防止主线程堵塞,增加运
Wesley13 Wesley13
4年前
JAVA多线程下载网络文件
JAVA多线程下载网络文件,开启多个线程,同时下载网络文件。importjava.io.InputStream;importjava.io.RandomAccessFile;importjava.net.HttpURLConnection;importjava.net.URL;/\\ \说明: \每一个线程下载的位置计算
Wesley13 Wesley13
4年前
unity使用多线程下载时,删除正在下载的文件时候报如下错误
!(https://imgblog.csdnimg.cn/20201020195548792.png)错误原因:下面代码 ,正在操作下载文件流fsFile.OpenWrite(filePath);而此时,你又想使用下面代码,删除正在下载的文件File.Delete(vd.l
绣鸾 绣鸾
2年前
整站下载工具 SiteSucker 「Mac」
SiteSucker是一款非常实用的网站下载工具,具有多种下载方式、支持下载整个网站或特定页面、支持多种文件格式、简单易用和支持多线程下载等特点。用户可以根据自己的需要选择要下载的网站或特定页面,然后选择下载文件的格式和数量,SiteSucker会自动将所
燕青 燕青
2年前
Downie 4 for Mac 兼容 14系统 中文版
是一款非常强大的视频下载工具,专门为Mac用户设计。它支持从各种不同的视频分享网站下载视频,包括YouTube、Vimeo、Netflix、HBO、BBC、Facebook等,并且可以同时下载多个视频。Downie4具有一键下载、批量下载和多线程下载等功能
公孙晃 公孙晃
2年前
Mac最好用的视频下载工具:Downie 4 for Mac中文破解版 支持M1
是一款专为Mac用户设计的视频下载工具。其非常易于使用,只需要把视频链接拖到Downie的窗口中,就可以轻松下载视频文件。Downie4forMac还支持多线程下载,下载速度非常快,而且可以自动检测和分类视频文件。此外,Downie4forMac拥有广泛的