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();
    }

总结

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值