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实现多线程下载

多线程加速下载:【1】不是说线程开的越多下载就快(手机迅雷建议开3-4个线程就好) 【2】还受服务器带宽的影响 【3】更多的cpu资源给了你多线程下载分析:每个线程下载的计算公式:JavaSE多线...

JavaSE多线程下载及断点续传

1、用到的知识点: (1)Java多线程 (2)Java I/O (3)一个重要的类:RandomAccessFile,该类可实现文件的随机读取,具体参见JDK。 (4)Java net相关知识 2、...

JavaSE_6_多线程

  • 2017年02月09日 15:04
  • 432KB
  • 下载

JavaSE(19)(两种开启多线程方式)

TestFor类: package zz.itheima.multithread;public class TestFor { public static void main(String[] ...

JavaSE学习笔记_10:Java多线程

Java多线程   1、线程概述 我们都知道进程,进程是一个正在执行的程序。如qq,酷狗等,是一个明确的概念。而线程就是进程中的一个独立的控制单元或者叫做一个独立的执行路径,控制着进程的执行,线程包含...

黑马程序员-JAVASE入门(多线程)

------- android培训、java培训、期待与您交流! ----------

黑马程序员_JavaSE基础12 之 导入包 多线程的创建

---------------------- android培训、java培训、期待与您交流! --------------------- JavaSE_12  笔记  ...
  • Mary_k
  • Mary_k
  • 2012年09月11日 16:02
  • 435

JavaSE学习笔记之多线程

线程不同于进程。多线程操作多线程并发访问共享资源容易出现问题需要手动。...

JavaSE(20)(多线程安全)

Father类: package zz.itheima.multi_thread_security; //嵌套锁是为了让死锁出现的概率大大增加 public class Father extends ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaSE_多线程下载
举报原因:
原因补充:

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