zoukankan      html  css  js  c++  java
  • 安卓学习之路 -- JAVA多线程下载

    代码没有优化,暂时先实现结果

    package download;
    
    import java.io.File;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    /**
     * @author Liu Yutao
     * @className Down
     * @email koal@vip.qq.com
     * @date 2016/4/7 21:11
     */
    
    public class Down {
    
        //下载地址
        public static final String DOWNFILE = "http://219.150.176.188/files/WindowsXP_SP2.exe";
        //线程数
        public static final int THREADCOUNT = 5;
    
    
        //格式化文件,得到文件名称
        public static String formatFileName(String value) {
            //得到最后一个/位置
            int indexOf = value.lastIndexOf("/");
            //截取/WindowsXP_SP2.exe文件名
            String fileName = value.substring(indexOf + 1, value.length());
            return fileName;
        }
    
        //下载文件
        public static void httpDownload(String downfile) {
            try {
                URL url = new URL(DOWNFILE);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                //超时5秒
                connection.setReadTimeout(5000);
                connection.setRequestMethod("GET");
                int code = connection.getResponseCode();
                if (code == 200) {
                    //得到文件长度
                    long length = connection.getContentLength();
                    InputStream stream = connection.getInputStream();
                    File file = new File(formatFileName(DOWNFILE));
                    //用于创建一个和目标文件大小一样的空文件,为了就是占坑(rw是可读可写模式read,write)
                    RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
                    accessFile.setLength(length);
                    //分10个线程,每个线程的区块长度(总长度 ÷ 个数)
                    long blockSize = length / THREADCOUNT;
                    for (int threadId = 0; threadId < THREADCOUNT; threadId++) {
                        //开始区块
                        // 当前循环线程编号 x 当前线程区块长度(0x1024,1x1024,2x1024)
                        long beginIndex = threadId * blockSize;
                        //结束区块
                        // 当前线程+1 x 每个区块大小 = 下次循环的开始区块,再 -1 就等于本次区块的最后位置
                        long endIndex = (threadId + 1) * blockSize - 1;
                        //是否最后一个线程
                        if (threadId == (THREADCOUNT - 1)) {
                            endIndex = length - 1;
                        }
                        System.err.println("当前线程:" + (threadId+1) + ",开始区块:" + beginIndex + ",结束区块:" + endIndex);
                        new ThreadDownloadRun(threadId, beginIndex, endIndex).start();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static class ThreadDownloadRun extends Thread {
    
            private long threadId;
            private long beginIndex;
            private long endIndex;
    
            //构造
            public ThreadDownloadRun(long threadId, long beginIndex, long endIndex) {
                this.threadId = threadId;
                this.beginIndex = beginIndex;
                this.endIndex = endIndex;
            }
    
            @Override
            public void run() {
                try {
                    System.err.println("当前线程:" + (threadId+1) + ",开始下载......");
                    URL url = new URL(DOWNFILE);
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    //设置http文件头的range(区间)
                    urlConnection.setRequestProperty("Range", "bytes=" + beginIndex + "-" + endIndex);
                    int code = urlConnection.getResponseCode();
                    //区间返回是206
                    if (code == 206) {
                        //得到数据
                        InputStream stream = urlConnection.getInputStream();
                        File file = new File(formatFileName(DOWNFILE));
                        RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
                        //设置RandomAccessFile写入文件的区块开始长度
                        accessFile.seek(beginIndex);
                        //下载开始
                        byte[] bytes = new byte[1024 * 1024];
                        int len = 0;
                        while ((len = stream.read(bytes)) > 0) {
                            accessFile.write(bytes, 0, len);
                        }
                        accessFile.close();
                        stream.close();
                        System.err.println("当前线程:" + (threadId+1) + ",下载结束!!!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            httpDownload(DOWNFILE);
        }
    }

  • 相关阅读:
    vue状态管理vuex+slot插槽+vue-resource请求
    海豚调度Dolphinscheduler源码分析(三)
    记录一次Curator操作zookeeper的错误
    海豚调度Dolphinscheduler源码分析(二)
    海豚调度DolphinScheduler源码分析(一)
    Java 基础(方法参数的值传递机制)
    Java 基础(匿名对象, 方法重载, 可变个数的形参)
    Java 练习(创建类, 设计类Circle计算圆的面积, 对象数组)
    Java 基础(类中属性与局部变量比较; 方法的分类)
    Java 基础(面向对象; 类和对象)
  • 原文地址:https://www.cnblogs.com/koal/p/5366127.html
Copyright © 2011-2022 走看看