多线程下载

来源:互联网 发布:好吃的威化饼 知乎 编辑:程序博客网 时间:2024/06/05 04:48

多线程下载

流 randomAccessFile

public class Demo_1 {    public static void main(String[] args) throws Exception  {        //要下载的文件地址        String path = "http://10.40.155.230:8080/down/down.mp3";        //创建对象 调用下载文件方法 传入路径 和线程数        new Demo_1().download(path, 3);    }    private String getFileName(String path) {        //如果包含有"/"号 从最后一个"/"号 +1 的位置开始截取字符串        return path.substring(path.lastIndexOf("/")+1);    }    /*下载文件     * path 网络文件的路径     * threadSize 线程数     * */    private void download(String path,int threadSize) throws Exception {        //URL(String spec)         URL url = new URL(path);        //使用jdk自带的 HttpURLConnection向 URL发送 请求并输出响应结果        HttpURLConnection connection = (HttpURLConnection)url.openConnection();        //请求方式  设置        connection.setRequestMethod("GET");        //连接超时 设置        connection.setConnectTimeout(5000);        /*http请求 状态码         * 200 成功 连上了服务器          * 4xx 客户端有问题         * 5xx 服务器端有问题         * */        if(connection.getResponseCode() == 200) {            //1 获取网络文件的长度            int length = connection.getContentLength();            //本地文件            File file = new File(getFileName(path));            //在本地生成一个长度与网络文件相同的文件            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");            accessFile.setLength(length);//将获取到的网络文件的长度 当成本地文件的长度            accessFile.close();            //计算每条线程负责下载的数据量 10%3 每一条线程分配的数据量  宁多不少原则            int block = length % threadSize == 0 ? length/threadSize : length/threadSize + 1;            //循环创建3个线程             for(int threadId = 0;threadId < threadSize;threadId++) {                //线程号 每条线程负责的数量 地址 存储位置 启动线程                new DownloadThread(threadId,block,url,file).start();            }        }else {            System.out.println("连接失败");        }    }    private class DownloadThread extends Thread{        private int threadId; //线程号        private int block; //每条线程负责处理的数量        private URL url; //地址        private File file; //本地位置        public DownloadThread(int threadId,int block,URL url,File file) {            this.threadId = threadId;            this.block = block;            this.url = url;            this.file = file;        }        public void run() {            //计算线程从网络文件的什么位置开始下载            // 例如 文件长度 是 4 平均 每一块 2 threadId 0 block 2             //第一次 0 1 第二次 2 3 第三次 4 5            int start = threadId * block;            //计算下载到网络文件结束位置            int end = (threadId + 1) * block - 1;            try {                RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");                //每次从start位置开始 指针发生改变                 accessFile.seek(start);                //使用jdk自带的 HttpURLConnection向 URL发送 请求并输出响应结果                HttpURLConnection connection = (HttpURLConnection)url.openConnection();                //请求方式  设置                connection.setRequestMethod("GET");                //连接超时 设置                connection.setConnectTimeout(5000);                //Range                connection.setRequestProperty("Range", "bytes="+start+"-"+end);                //注意 多线程下载的状态码 是 206 不是 200                if(connection.getResponseCode() == 206) {                    //流 将 要下载的内容 存入到自己的硬盘上                    InputStream inputStream = connection.getInputStream();                    byte[] buffer = new byte[1024];                    int len = 0;                    while((len = inputStream.read(buffer))!=-1) {                        //将数据 写出到硬盘文件上                        accessFile.write(buffer,0,len);                    }                    //关闭资源 释放流                    accessFile.close();                    inputStream.close();                }                System.out.println("第"+(threadId+1)+"条线程已经下载完成");            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();            }         }    }}