影响下载的速度

* 宽带的带宽

* 服务器的限制

* 服务器的资源固定,开启的线程越多抢占的资源就越多

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

public class MultiDownLoad {

   static String path = http://192.168.3.100:8080/web/download/gui.exe;
static int threadCount = 3; /**
* 获取文件的存储路径
*/ static String getFilePath(){ int index = path.lastIndexOf("/")+1; return "D:\\"+path.substring(index); }
public static void main(String[] args) { try {
// 1. 在客户端创建和服务器资源一样大小的空文件 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(3000); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); //服务器资源文件的大小 int fileLength = 0; if (code == 200) { fileLength = conn.getContentLength(); System.out.println("文件大小:"+fileLength); // //可选,可以不写,检测硬盘的空间够不够用 // RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw"); // //在硬盘上创建控件 // raf.setLength(fileLength); // raf.close(); } //每个线程下载的区块大小 int blockSize = fileLength / threadCount; // 2. 客户端开启多个线程去下载服务器的资源 for (int threadId = 0; threadId < threadCount; threadId++) { int startIndex = threadId * blockSize; int endIndex = (threadId + 1)* blockSize -1; //最后一个线程,修正下载的结束位置 if (threadId == threadCount-1) { endIndex = fileLength - 1; } //开启线程 new DownLoadThread(startIndex, endIndex, threadId).start(); } } catch (Exception e) { e.printStackTrace(); } } static class DownLoadThread extends Thread { //开始位置 int startIndex; //结束位置 int endIndex; //线程ID int threadId; public DownLoadThread(int startIndex, int endIndex, int threadId) { super(); this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { super.run(); System.out.println("线程 : "+ threadId + " : "+ startIndex+" ~ "+endIndex); try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(3000); //重要,设置请求的范围 conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex); //部分请求成功 206 int code = conn.getResponseCode(); System.out.println(" code = "+code); if (code == 206) { RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw"); //重要,写文件之前定位 raf.seek(startIndex); //获取这个线程对应的一块资源 InputStream is = conn.getInputStream(); byte[] buffer = new byte[1024*8]; int len = -1; while((len = is.read(buffer)) != -1){ raf.write(buffer, 0, len); } raf.close();
} // 3. 每个线程都下载完毕,整个资源就下载完了 System.out.println("线程 "+threadId+" 干完活了!"); } catch (Exception e) { e.printStackTrace(); } } } }

最新文章

  1. Log4net入门(日志文件篇)
  2. 实践 Neutron 前的两个准备工作 - 每天5分钟玩转 OpenStack(78)
  3. Angular自定义指令directive:scope属性
  4. hadooop 运维之 container error exit code 1
  5. Windows远程桌面连接Ubuntu 14.04
  6. C#利用SharpZipLib解压或压缩文件夹实例操作
  7. 蓝牙音箱bose soundlink mini2链接mac后itunes自动启动的问题解决
  8. 设置imageView正方形高宽
  9. 【原创】leetCodeOj ---Convert Sorted List to Binary Search Tree 解题报告
  10. 如何写兼容浏览器和Node.js环境的Javascript代码
  11. Spring MVC URL的映射问题 ;Spring MVC 跳转与iframe包含地址问题
  12. 你需要了解的 Core Spotlight
  13. 按Enter登录,Esc退出
  14. Jmeter 非 GUI 命令行执行脚本文件
  15. xdoj-1297 Tr0y And His Startup
  16. JavaScript——变量
  17. react给一个div行内加背景图片并实现cover覆盖模式居中显示
  18. [Leetcode]316.去除重复字母
  19. Connect to DB2 database in eclipse via jdbc
  20. No.4 PyQt学习(页面跳转)

热门文章

  1. sql 存储过程笔记3
  2. 为什么有了uwsgi还要nginx这个“前端”服务器
  3. kafka无法消费数据提示找不到分区
  4. Django项目实战—用户头像上传
  5. [shell] shell echo打印换行的方法
  6. 洛谷 P2756 飞行员配对方案问题 (二分图/网络流,最佳匹配方案)
  7. Sleep-Join方法理解
  8. Nginx之什么是反向代理(一)
  9. vue今日总结
  10. SQL Server text field里面有换行符的时候copy到excel数据会散乱