Android多线程下载

背景

万事都有两面性,多线程下载也是,那么多线程下载的优点是什么呢?归根结底还是多线程的优点,这里我们暂且不去讨论它的利弊,只是讲解一下思想和实现方案。

实现分析

我们用五个why的思想来分析一下这个问题:

  1. 怎么实现多线程下载?
    将下载逻辑在多个线程中同时运行。
  2. 怎么让每个线程下载对应的文件?
    将文件拆分成线程数对应的分数,进行分配。
  3. 怎么拆分文件?
    获取文件的长度,再按照线程数进行按比例分配。
  4. 怎么获取文件长度?
    利用HttpURLConnection的方法来获取内容长度
  5. 下载完成之后怎么办?
    各个线程都下载完成之后利用RandomAccessFile进行文件合并

好了,分析到这我们感觉已经可以实现了,我们再重新梳理一下逻辑,大概是,设定线程的数量,按照线程数量来分割要下载的文件,启动多个线程进行下载,最后合成一个文件。OK,撸起袖子就是干!

代码实现

1、设置线程数,我这边是默认指定了三个,大家也可以通过服务器配置啊,或者某些算法来计算需要的线程数,根据实际情况来定。
2、获取文件长度:

  URL url = new URL(file.url);
  HttpURLConnection con = (HttpURLConnection)
  url.openConnection();
  con.setRequestMethod("GET");
  con.setConnectTimeout(5000);
  if(con.getResponseCode() ==  HttpURLConnection.HTTP_OK) {
    int len = con.getContentLength(); //文件的总长度
  }

这样我们就获取到了文件的长度,然后就可以分割下载了,当然之前我们要初始化一些路径啊,RandomAccessFile什么的,大家可以下载源码查看。
3、分割文件内容:

        List<ThreadInfo> threadInfoList = new LinkedList<ThreadInfo>(); //建立线程信息列表
            int block = mDownloadInfo.lenght/mThreadCount; //将下载文件分段
            if(block > 0) {
                //start 根据线程数量分别建立线程信息
                for(int i = 0;i < mThreadCount;i++) {
                    ThreadInfo info = new ThreadInfo(i,mDownloadInfo.url,i*block,(i+1)*block-1,0);
                    if(i == mThreadCount -1) {
                        info.end = mDownloadInfo.lenght; //分段最后一个,结束位置到文件总长度末尾
                    }
                    threadInfoList.add(info);         //加入列表
                }
                //end 根据线程数量分别建立线程信息

4、启动下载线程:

        //start 启动下载线程
        for(ThreadInfo info : threadInfoList) {
            DownloadThread thread = new DownloadThread(info,mDownloadInfo,mTotalFinished);
            if(!mThreadPool.isShutdown()) {
                mThreadPool.execute(thread);
            }

        }

5、下载的逻辑和RandomAccessFile最后生成一个完整的文件:

    public void run() {
        URL url = null;
        HttpURLConnection con = null;      //http链接
        RandomAccessFile accessFile = null; //下载文件
        InputStream inputStream = null;      //输入流
        try {

            int start = threadInfo.start+threadInfo.finished; //读取文件的位置
            //start 初始化下载链接
            url = new URL(threadInfo.url);
            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.setConnectTimeout(5000);
            con.setRequestProperty("Range", "bytes=" + start + "-" + threadInfo.end); //设置读取文件的位置,和结束位置
            //end 初始化下载链接
            //start 初始化下载到本地的文件
            accessFile  = new RandomAccessFile(new File(downloadInfo.filePath, downloadInfo.fileName),"rwd");
            accessFile.seek(start);    //设置开始写入的位置
            //end 初始化下载到本地的文件

            int responseCode = con.getResponseCode();
            if((con.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) ||
                    (con.getResponseCode() == HttpURLConnection.HTTP_OK) ) {
                inputStream = con.getInputStream();
                int finished = threadInfo.finished;               //已经下载的长度
                int readLen = -1;                                       //读取的长度
                byte[] buffer = new byte[1024*4];
                long time = System.currentTimeMillis();

                //start 读取输入流写入文件
                while((readLen = inputStream.read(buffer))!=-1) {
                    accessFile.write(buffer, 0, readLen);
                 );
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            try {
                if(inputStream!=null){
                    inputStream.close();
                }
                if(accessFile!=null) {
                    accessFile.close();
                }
                if(null!=con) {
                    con.disconnect();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        super.run();
    }

总结

好了,主要下载逻辑就是这样,大家想看完整代码的可以点击下面的链接,希望大家可以喜欢,谢谢!
源码下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Android 多线程下载,断点续传 https://github.com/liu8021203/Download...
    笑哈哈的精彩阅读 640评论 0 2
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,401评论 25 707
  • 概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先...
    SmileUsers阅读 6,459评论 8 35
  • 真心讨厌现在的自己。不喜欢就别暧昧呀,真是沾花惹草,可以果断一点吗,别那么随便好嘛?
    爱吃煎饼果子阅读 148评论 0 0
  • 爸妈在工厂上班,同住一套房的有一对夫妻俩,带着两个小孩子,一个儿子,一个女儿,儿子七八岁,女儿大约三四岁,都活泼可...
    墨瞳_3611阅读 354评论 0 2