手动多线程断点下载

多线程加速下载原理:

1,服务器资源是固定的,开启的线程越多,抢占的资源越多


2,宽带的带宽


3,服务器的限制



    private void downloadApk() {
        try {
            private static int threadCount = 3;
            URL url = new URL(path);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(3000);
            int code = conn.getResponseCode();

            int fileLength = 0;
            if (code == 200) {
                //1.获取服务器资源文件的大小
                fileLength = conn.getContentLength();
                //在本地创建一个相同大小的空文件
                RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
                raf.setLength(fileLength);
                raf.close();
            }
            //2.开启多个线程对应服务器的一块儿资源
            //每个线程下载的区块儿大小
            int blockSize = fileLength/threadCount;
            for (int threadId = 0; threadId < threadCount; threadId++) {
                int startIndex = threadId * blockSize;
                int endIndex = (threadId + 1) * blockSize - 1;
                //最后一个线程结束位置
                if (threadId == threadCount - 1) {
                    endIndex = fileLength - 1;
                }
                new downloadThread(startIndex, endIndex, threadId).start();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static class downloadThread extends Thread {
        //开始位置
        int startIndex;
        //结束位置
        int endIndex;
        //线程id
        int threadId;
        //断点的位置
        int lastDownPos;

        public downloadThread(int startIndex, int endIndex, int threadId) {
            super();
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
            //初始化
            lastDownPos = startIndex;
        }
        @Override
        public void run() {
            super.run();
            //每个线程下载一个对应的服务器资源区块儿
            try {
                //读取存储的断点的位置
                File file = new File(getTempFilePath(threadId));
                if (file.exists() && file.length() > 0) {
                    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
                    //获取断点上次存储的位置
                    lastDownPos = Integer.valueOf(br.readLine());
                    //修改开始下载的位置
                    startIndex = lastDownPos;
                    br.close();
                }
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(3000);
                //设置当前线程请求资源的范围
                conn.setRequestProperty("Range", "bytes = " + startIndex + "-" + endIndex);
                int code = conn.getResponseCode();
                InputStream is = conn.getInputStream();
                if (code == 206) {
                    RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
                    //定位写文件的位置
                    raf.seek(startIndex);
                    //读取流
                    byte[] buffer = new byte[1024 * 8];
                    int lenth= -1;
                    while ((lenth = is.read(buffer)) != -1) {
                        raf.write(buffer, 0, lenth);
                        //存储断点的位置
                        RandomAccessFile r = new RandomAccessFile(getTempFilePath(threadId), "rw");
                        //用临时文件存储相对于整个文件的位置
                        lastDownPos += lenth;
                        r.write(String.valueOf(lastDownPos).getBytes());
                        r.close();
                    }
                    raf.close();
                }
                //3,每个线程都干完活 , 整个资源就下载完了
                file.delete();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static String getFilePath() {
        int index = path.lastIndexOf("/") + 1;
        return path.substring(index);
    }

    public static String getTempFilePath(int threadId) {
        return getFilePath() + threadId + ".txt";
    }

多线程下载与单线程下载是一样的,无非是多了一个循环,自己控制开启的线程数

断点只是定义了一个Int类型的变量,把控它的位置,细心+耐心,everyone can do it.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值