JavaSE_多线程下载

原创 2016年06月01日 14:01:58

多线程下载

所谓多线程下载,就是将目标数据分成若干个段,每个线程负责请求、写入一段数据的下载方式,这种方式可以解决由于单线程运算速度不能发挥所有网络带宽导致的慢速,但并不会突破物理网络的最大速度。用java实现多线程下载不需要第三方框架或jar包,只是基本的网络请求和读写操作就可以完成。

用来测试的文件最好选择可执行文件,因为如果选择图片或视频等文件,即使传输过程中出现了小部分数据的错误,也难以排查。


步骤

计算每个线程需要下载多少数据,从多少开始,到多少结束,这需要请求到所有的数据,获取数据的长度,就可以根据线程的数量来分配目标数据了,得到之后就可以开启线程下载了

代码

        try {
            //发送目标文件的请求,拿到文件长度
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(8000);
            conn.setReadTimeout(8000);
            conn.setRequestMethod("GET");

            if (conn.getResponseCode() == 200) {
                //获取长度
                int length = conn.getContentLength();
                //获取文件名
                String fileName = getFileNameFromPath(path);

                //创建临时文件
                File file = new File(fileName);
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");//这样文件就可以直接写到磁盘上,不经过缓冲区了。
                raf.setLength(length);//设置文件的大小

                //raf使命完成,关闭资源
                raf.close();

                //计算每个线程需要下载多少数据
                int size = length / threadCount;

                //用循环计算每个线程的下载区间,并开启线程下载
                for (int i = 0; i < threadCount; i++) {
                    int startIndex = i * size;
                    int endIndex = (i + 1) * size - 1;
                    if (i == threadCount -1){//如果是最后一个,就把剩下的全部下载完!
                        endIndex = length-1;
                    }

                    Thread thread = new MyThread(i,startIndex,endIndex);
                    thread.start();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
其中文件输出流使用RandomAccessFile的原因是能够直接将数据写入到磁盘上而不是先写入缓冲区在适当时再写入磁盘。

Java帮助文档原文:

"rws""rwd" 模式的工作方式极其类似FileChannel 类的 force(boolean) 方法,分别传递 truefalse 参数,除非它们始终应用于每个 I/O 操作,并因此通常更为高效。如果该文件位于本地存储设备上,那么当返回此类的一个方法的调用时,可以保证由该调用对此文件所做的所有更改均被写入该设备。这对确保在系统崩溃时不会丢失重要信息特别有用。如果该文件不在本地设备上,则无法提供这样的保证。


其中用for循环得到每个线程请求的目标数据信息后,开始自定义的线程对象实例,这个自定义线程对象就得到了请求数据的信息,可以在线程对象的run方法中使用了。

自定义的Thread代码

    static class MyThread extends Thread{

        private int tid, startIndex,endIndex;

        public MyThread(int tid, int startIndex, int endIndex) {
            this.tid = tid;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(8000);
                conn.setConnectTimeout(8000);
                conn.setRequestMethod("GET");
                //设置请求的数据区间
                conn.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);

                if (conn.getResponseCode() == 206){//请求部分数据成功的响应码是206
                    InputStream is = conn.getInputStream();
                    int len;
                    byte[] buf = new byte[1024];
                    File file = new File(getFileNameFromPath(path));
                    RandomAccessFile raf = new RandomAccessFile(file,"rwd");
                    raf.seek(startIndex);//设置输出流写入的开始位置

                    while ((len = is.read(buf))!=-1){
                        raf.write(buf,0,len);
                    }
                    is.close();
                    raf.close();
                    System.out.println("第"+tid+"下载完毕");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
其中需要注意 Http请求部分部分数据成功得到的响应式206,并不是200。
其中必须要在连接中声明要请求的数据的区间,也要声明输出流写入文件的位置。

版权声明:本文为Mr.Seng原创文章,转载注明地址:http://blog.csdn.net/mr_seng 举报

相关文章推荐

JavaSE_多线程下载

多线程下载 所谓多线程下载,就是将目标数据分成若干个段,每个线程负责请求、写入一段数据的下载方式,这种方式可以解决由于单线程运算速度不能发挥所有网络带宽导致的慢速,但并不会突破物理网络的最大速度。用...

JavaSE_多线程

1、课程名称:多线程 2、知识点 2.1、本次预计讲解的知识点 1、 了解进程和线程的区别 2、 理解Java线程的两种实现方法及区别 • 可以清楚的解释出两种实现的方式、区别、...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

JAVASE_多线程

java中产生线程的方式有两种,第一种是:继承Thread类,并覆盖其run方法 第二种是:实现Runnable接口中的run方法 *注意:run中实现的代码,就是多线程要执行的代码 Re...

单线程下载和多线程下载

单线程下载1.单线程下载比较简单,就是开启一个线程,然后打开URL连接按照字节的方式读取流,写入文件就可了 2.用AsyncTask实现单线程下载class DownLoadSingle exten...

多线程05-cell照片下载

// // HMAppsViewController.m // 01-cell图片下载(了解) // // Created by apple on 14-9-18. // Copyright ...

多线程下载

实现这个功能需要用到一个类RandomAccessFile,它既不是继承于InputStream也不继承于OutputStream, 直接继承于Object类,它能够实现在文件里面前后移动,在文件里...

使用多线程下载同一个文件

理解:将服务器的一个资源分成多个部分,每个线程复制下载其中一个部分,然后设置每个线程对同一个文件开始写入的位置,当所有线程下载完成后,本地文件便是一个完整的文件了。   需要的权限:   ac...

使用HttpUrlConnection多线程下载文件

package com.example.administrator.myapplication; import java.io.IOException; import java.io.InputSt...

多线程下载

public class MainActivity111 {       //初始化线程数量 与网络路径     static int Threadcount=3;     stat...

java网络编程之下载文件通过多线程分块下载(二)

import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAc...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)