多线程下载文件

多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可。

涉及的知识及问题

  • 请求的数据怎么拆分
  • 拆分完成后怎么下载
  • 如何计算实时下载量

一.请求的数据怎么拆分

 int blockSize =fileLength/threadCount; //计算每个线程需要下的长度
for(int i=0;i<threadCount;i++) {
int startSize=i*blockSize; //当前线程需要下载的开始位置
int endSize=(i+1)*blockSize-1;//当前线程需要下载的结束位置
if(1+i==threadCount) { //最后一个线程的结尾赋值文件大小
endSize=fileLength;
}
threadList[i]= new DownThread_1(filePath, fileUrl, "线程"+i, startSize, endSize);
threadList[i].start();
}

二.拆分完成后怎么下载

try {
URL url = new URL(urlPath);
HttpURLConnection coon = (HttpURLConnection) url.openConnection();
coon.setRequestProperty("range","bytes="+startSize+"-"+endSize); //设置获取下载资源的开始位置和结束位置
coon.setConnectTimeout(5000);
if(coon.getResponseCode()==206) {//响应码 因为上面设置了range 所有响应码是206不再是200
BufferedInputStream bi=new BufferedInputStream(coon.getInputStream());
RandomAccessFile raf=new RandomAccessFile(filePath, "rwd"); //断点续传的关键
raf.seek(startSize); //将写入点移动到当前线程写入开始位置
byte b[]=new byte[1024];
int len=0;
while ((len=bi.read(b))>-1) { //循环写入
raf.write(b, 0, len);
synchronized (DownUtile.class) {//此处涉及到变量同步
DownUtile.downLength=DownUtile.downLength+len; //计算当前下载了多少
}
}
raf.close();
bi.close();
System.out.println("thread"+threadName+"下载完成,开始位置"+startSize+",结束位置"+endSize);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

三.如何计算实时下载量

    while ((len=bi.read(b))>-1) { //循环写入
raf.write(b, 0, len);
synchronized (DownUtile.class) {//此处涉及到变量同步
DownUtile.downLength=DownUtile.downLength+len; //计算当前下载了多少
}
} while(DownUtile.downOver) {
Thread.sleep(500); //间隔0.5秒计算一下
if(DownUtile.downLength==fileLength) {
DownUtile.downOver=false;
System.out.println("下载完成:100%");
}else {
System.out.println("已经下载了:"+((int) (float)DownUtile.downLength / (float) fileLength * 100)+"%");
}
}

上述方法中  用到了synchronized(类锁),为什么用到类锁,因为计算下载的参数在DownUtile类中,为了保证这个参数在多线程中同步,需保证在执行累加操作时线程安全。

下面贴上全部的代码

 public class DownLoadUtile {
public static String filePath="C:\\Users\\Administrator\\Desktop\\下载\\ deme.exe"; //文件保存地址
public static String fileUrl="http://123.6.39.120/dlied1.qq.com/lol/dltools/LOL_V4.1.2.3-V4.1.2.4_PATCH_0_tgod_signed.exe?mkey=5cfc8d87dddd9a57&f=5844&cip=221.221.188.162&proto=http";//文件地址
public static int threadCount=5; //线程数量
public static int fileLength=0; //文件大小
public static Thread [] threadList=new Thread[threadCount]; public DownLoadUtile() { }
public DownLoadUtile(int threadCount) {//有参构造
this.threadCount=threadCount;
} public static void main(String[] args) throws Exception {
URL url=new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //创建连接对象
conn.setConnectTimeout(5000);//请求超时时间 int code = conn.getResponseCode();
System.out.println("服务器响应码"+code);
if(code==200) {//响应正常
fileLength=conn.getContentLength(); //获取文件大小
File file = new File(filePath);
if(!file.exists()) {
file.createNewFile();
}
RandomAccessFile raf = new RandomAccessFile(filePath, "rwd"); //断点续传的关键
raf.setLength(fileLength); int blockSize =fileLength/threadCount; //计算每个线程需要下的长度
for(int i=0;i<threadCount;i++) {
int startSize=i*blockSize; //当前线程需要下载的开始位置
int endSize=(i+1)*blockSize-1;//当前线程需要下载的结束位置
if(1+i==threadCount) { //最后一个线程的结尾赋值文件大小
endSize=fileLength;
}
threadList[i]= new DownThread_1(filePath, fileUrl, "线程"+i, startSize, endSize);
threadList[i].start();
} while(DownUtile.downOver) {
Thread.sleep(500); //间隔0.5秒计算一下
if(DownUtile.downLength==fileLength) {
DownUtile.downOver=false;
System.out.println("下载完成:100%");
}else {
System.out.println("已经下载了:"+((int) (float)DownUtile.downLength / (float) fileLength * 100)+"%");
}
} }else {
System.out.println("服务器响应失败"+code);
} }

下载类

 public class DownThread_1 extends Thread{

     private String filePath;
private String urlPath;
private String threadName;
private int startSize;
private int endSize; public DownThread_1(String filePath,String urlPath,String threadName,int startSize,int endSize) {
this.endSize=endSize;
this.startSize=startSize;
this.filePath=filePath;
this.urlPath=urlPath;
this.threadName=threadName;
}
@Override
public void run() {
try {
URL url = new URL(urlPath);
HttpURLConnection coon = (HttpURLConnection) url.openConnection();
coon.setRequestProperty("range","bytes="+startSize+"-"+endSize); //设置获取下载资源的开始位置和结束位置
coon.setConnectTimeout(5000);
if(coon.getResponseCode()==206) {//响应码 因为上面设置了range 所有响应码是206不再是200
BufferedInputStream bi=new BufferedInputStream(coon.getInputStream());
RandomAccessFile raf=new RandomAccessFile(filePath, "rwd"); //断点续传的关键
raf.seek(startSize); //将写入点移动到当前线程写入开始位置
byte b[]=new byte[1024];
int len=0;
while ((len=bi.read(b))>-1) { //循环写入
raf.write(b, 0, len);
synchronized (DownUtile.class) {//此处涉及到变量同步
DownUtile.downLength=DownUtile.downLength+len; //计算当前下载了多少
}
}
raf.close();
bi.close();
System.out.println("thread"+threadName+"下载完成,开始位置"+startSize+",结束位置"+endSize);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} }

参数类

 public class DownUtile {

     public static  int downLength=0;//已经下载了多少

     public static boolean downOver=true; //下载是否完成

 }

java 多线程下载文件并实时计算下载百分比(断点续传)的更多相关文章

  1. [Swift通天遁地]四、网络和线程-(8)下载图片并实时显示下载进度

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. JAVA多线程读写文件范例

    在写之前先声明,本文是基于之前在博客园网站上检索到的一份JAVA多线程读写文件的示例,我在写自己的程序时是在那位作者写的基础上做了改良,但已不记得原文的地址.如果有知情者,烦请帖出地址,我在此文上加入 ...

  3. 09_多线程下载_获取文件长度&计算下载范围

    package com.itheima.multiThreadDownload; //import java.net.MalformedURLException; import java.io.Ran ...

  4. Java实现FTP文件上传与下载

    实现FTP文件上传与下载可以通过以下两种种方式实现(不知道还有没有其他方式),分别为:1.通过JDK自带的API实现:2.通过Apache提供的API是实现. 第一种方式 package com.cl ...

  5. Java实现对文件的上传下载操作

    通过servlet,实现对文件的上传功能 1.首先创建一个上传UploadHandleServlet ,代码如下: package me.gacl.web.controller; import jav ...

  6. 【Java】JavaWeb文件上传和下载

    文件上传和下载在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用java开发的文件上传组件,本文以commons-fileupload组件为例,为jsp应用添加文件 ...

  7. java实现大文件上传和下载

    [文件上传和下载]是很多系统必备功能, 比如PM\OA\ERP等:系统中常见的开发模式有B/S和C/S,而前者主要是通过浏览器来访问web服务器,一般采用七层协议中的[应用层http]进行数据传输,后 ...

  8. Java 实现ftp 文件上传、下载和删除

    本文利用apache ftp工具实现文件的上传下载和删除.具体如下: 1.下载相应的jar包 commons-net-1.4.1.jar 2.实现代码如下: public class FtpUtils ...

  9. Java中的文件上传和下载

    文件上传原理: 早期的文件上传机制: 在TCP/IP中.最早出现的文件上传机制是FTP.他是将文件由客户端发送到服务器的标准机制. jsp中的文件上传机制: 在jsp编程中不能使用FTP的方法来上传文 ...

随机推荐

  1. SDUT OJ 2616 简单计算

    简单计算 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 某天,XX 给YY 出了一道题,题目是: 给出n 个十进制的数,找出这n ...

  2. Matlab的publish功能和cell功能

    Matlab的publish功能能够让写的代码变成优美的文档.类似为知笔记的markdown语言. cell功能配合publish使用,可以形成不同的功能块.而且调试的时候,可以按section调试. ...

  3. CSS3实现自定义Checkbox动画

    CSS3实现自定义Checkbox动画是一款CSS3自定义checkbox,而且这款checkbox还带有动画效果,当你选中checkbox的时候,会以动画的方式打上一个大大的勾. 源码下载:http ...

  4. python基础-发邮件smtp

    先来想下发送邮件需要填写什么,还需要有什么条件1.与邮件服务器建立连接,用户名和密码2.发邮件:发件人,收件人,主题,内容,附件3.发送 使用第三方邮箱发送邮件 #! /usr/bin/env pyt ...

  5. Apache-SimpleEmail 简单应用

    比JavaMail使用方法要直接,jar包只需要在JavaMail的基础上添加commons-email-1.4.jar即可. 代码: // QQ邮箱发送邮件 SimpleEmail simpleEm ...

  6. Java集合的有序无序问题和线程安全与否问题

    首先,清楚有序和无序是什么意思: 集合的有序.无序是指插入元素时,保持插入的顺序性,也就是先插入的元素优先放入集合的前面部分. 而排序是指插入元素后,集合中的元素是否自动排序.(例如升序排序) 1.有 ...

  7. struts2标签(转)

    Struts2 标签库讲解   要使用Struts2的标签,只需要在JSP页面添加如下一行定义即可: <%@ taglib prefix="s" uri="/str ...

  8. win7 jdk1.7配置环境变量

    1.安装目录,C:\Program Files\Java

  9. codeforces 558B B. Amr and The Large Array(水题)

    题目链接: B. Amr and The Large Array time limit per test 1 second memory limit per test 256 megabytes in ...

  10. 1076 Forwards on Weibo (30)(30 分)

    Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may ...