多线程下载

多线程下载

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值