手记

转 android 多线程下载

多线程下载在我们生活中非常常见,比如迅雷就是我们常用的多线程的下载工具,当然还有断点续传,断点续传我们在下一节来讲,android手机端下载文件时也可以用多线程下载,我们这里是在java中写一个测试,其实android中的实现和java是一样的,学会了java就知道怎么在android中实现了,废话不多说了,怎么实现多线程和多线程的原理是什么样的,现在我们来学习一下。

多线程下载原理及步骤:

1.    在本地创建一个大小跟服务器文件相同大小的临时文件。

2.    计算分配几个线程去下载服务器上的资源,知道每个线程下载文件的位置。

步骤二的具体方法和操作:

文件的长度/3(线程的个数)=每个线程下载文件的大小

假设文件长度为10,则

线程1:0-2

线程2:3-5

线程3:6-文件末尾

每个线程下载的位置的计算方式:

开始位置:

(线程id - 1)* 每一块的大小

结束位置:

(线程id * 每一块大小)-1

1.     开启多(3)个线程,每一个线程下载对应位置的文件

2.     如果所有的线程都把自己的数据下载完毕了,服务器上的资源就被下载到本地了。

在这里在介绍一个有关多线程下载的java中的相关类RandomAccessFile

RandomAccessFile 随机文件访问类

只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。通过seek()方法指定位置,定位文件,即可以指定随机写文件的时候从哪个位置开始写。利用这个类才能实现文件的多线程下载。

基本原理和相关介绍如上,就这些,现在我们看看代码:

[代码]java代码:

?

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

064

065

066

067

068

069

070

071

072

073

074

075

076

077

078

079

080

081

082

083

084

085

086

087

088

089

090

091

092

093

094

095

096

097

098

099

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

package net.loonggg.test;

 

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

 

/***

 * 多线程下载

 *

 * @author loonggg

 *

 */

public class MutilDownloader   {

    // 开启的线程的个数

    public static final int THREAD_COUNT = 3;

 

    public static void main(String[]   args) throws Exception   {

        String   path = "http://down.360safe.com/yunpan/360wangpan_setup.exe";

        //   连接服务器,获取一个文件,获取文件的长度,在本地创建一个大小跟服务器文件大小一样的临时文件

        URL   url = new URL(path);

        HttpURLConnection   conn = (HttpURLConnection) url.openConnection();

        //   设置网络请求超时时间

        conn.setConnectTimeout(5000);

        //   设置请求方式

        conn.setRequestMethod("GET");

        int code = conn.getResponseCode();

        if (code == 200) {

            //   服务器返回的数据的长度,实际就是文件的长度

            int length = conn.getContentLength();

            System.out.println("----文件总长度----" + length);

            //   在客户端本地创建出来一个大小跟服务器端文件一样大小的临时文件

            RandomAccessFile   raf = new RandomAccessFile("yunpan.exe",   "rwd");

            //   指定创建的这个文件的长度

            raf.setLength(length);

            //   关闭raf

            raf.close();

            //   假设是3个线程去下载资源

            //   平均每一个线程下载的文件的大小

            int blockSize = length / THREAD_COUNT;

            for (int threadId = 1; threadId <= THREAD_COUNT; threadId++) {

                //   计算每个线程下载的开始位置和结束位置

                int startIndex = (threadId - 1) * blockSize;

                int endIndex = threadId * blockSize - 1;

                if (threadId == THREAD_COUNT) {

                    endIndex   = length;

                }

                System.out.println("----threadId---" + threadId

                        +   "--startIndex--" + startIndex + "--endIndex--"

                        +   endIndex);

                //   开启每一个线程

                new DownloadThread(path, threadId,   startIndex, endIndex)

                        .start();

            }

        }

 

    }

 

    /**

     * 下载文件的子线程,每一个线程下载对应位置的文件

     *

     * @author   loonggg

     *

     */

    public static class DownloadThread   extends Thread   {

        private int threadId;

        private int startIndex;

        private int endIndex;

        private String path;

 

        /**

         *   @param path

         *              下载文件在服务器上的路径

         *   @param threadId

         *              线程id

         *   @param startIndex

         *              线程下载的开始位置

         *   @param endIndex

         *              线程下载的结束位置

         */

        public DownloadThread(String path, int threadId, int startIndex,

                int endIndex) {

            this.path   = path;

            this.threadId   = threadId;

            this.startIndex   = startIndex;

            this.endIndex   = endIndex;

        }

 

        @Override

        public void run() {

            try {

                URL   url = new URL(path);

                HttpURLConnection   conn = (HttpURLConnection) url

                        .openConnection();

                conn.setRequestMethod("GET");

                //   重要:请求服务器下载部分的文件 指定文件的位置

                conn.setRequestProperty("Range",   "bytes=" + startIndex + "-"

                        +   endIndex);

                conn.setConnectTimeout(5000);

                //   从服务器请求全部资源的状态码200 ok 如果从服务器请求部分资源的状态码206 ok

                int code = conn.getResponseCode();

                System.out.println("---code---" + code);

                InputStream   is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流

                RandomAccessFile   raf = new RandomAccessFile("yunpan.exe",   "rwd");

                //   随机写文件的时候从哪个位置开始写

                raf.seek(startIndex);//   定位文件

                int len = 0;

                byte[]   buffer = new byte[1024];

                while ((len = is.read(buffer)) != -1) {

                    raf.write(buffer,   0, len);

                }

                is.close();

                raf.close();

                System.out.println("线程" + threadId + ":下载完毕了!");

            }   catch (Exception   e) {

                e.printStackTrace();

            }

        }

    }

 

}

原文链接:http://www.apkbus.com/blog-843025-61516.html

0人推荐
随时随地看视频
慕课网APP