资讯专栏INFORMATION COLUMN

多线程下载

newsning / 1620人阅读

摘要:原理多线程下载的原理就是将要下载的文件分成若干份,其中每份都使用一个多带带的线程进行下载,这样对于文件的下载速度自然就提高了许多。总结多线程的关键就是分配好需要下载的进程,定位进程下载的准确位置,获取输入流读取数据,同时写入到文件的相应位置。

原理

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

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

封装

对于多线程下载我们可以将其封装到一个工具类中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...

关注

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64854.html

相关文章

  • 线程系列之学习线程下载的基本原理和基本用法(1)

    摘要:多线程下载原理及步骤在本地创建一个大小跟服务器文件相同大小的临时文件。在这里在介绍一个有关多线程下载的中的相关类随机文件访问类只有才有搜寻方法,而这个方法也只适用于文件。利用这个类才能实现文件的多线程下载。 多线程下载在我们生活中非常常见,比如迅雷就是我们常用的多线程的下载工具,当然还有断点续传,断点续传我们在下一节来讲,android手机端下载文件时也可以用多线程下载,我们这里是在j...

    darry 评论0 收藏0
  • Python爬虫之线程下载豆瓣Top250电影图片

    摘要:本次爬虫项目将会用到模块中的类,多线程豆瓣电影图片。总结通过上述两个爬虫程序的对比,我们不难发现,同样是下载豆瓣电影,个网页中的图片,在没有使用多线程的情况下,总共耗时约,而在使用多线程个线程的情况下,总共耗时约秒,效率整整提高了约倍。 爬虫项目介绍   本次爬虫项目将爬取豆瓣Top250电影的图片,其网址为:https://movie.douban.com/top250, 具体页面如...

    shiyang6017 评论0 收藏0
  • 通过网络图片小爬虫对比Python中单线程线(进)程的效率

    摘要:批评的人通常都会说的多线程编程太困难了,众所周知的全局解释器锁,或称使得多个线程的代码无法同时运行。多线程起步首先让我们来创建一个名为的模块。多进程可能比多线程更易使用,但需要消耗更大的内存。 批评 Python 的人通常都会说 Python 的多线程编程太困难了,众所周知的全局解释器锁(Global Interpreter Lock,或称 GIL)使得多个线程的 Python 代码无...

    W4n9Hu1 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<