java多线程实现文件下载 -九游会真人第一品牌

本文实例为大家分享了java多线程实现文件下载的具体代码,供大家参考,具体内容如下

1、downloadmanager类

import java.io.file;
import java.io.fileinputstream;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.net.httpurlconnection;
import java.net.malformedurlexception;
import java.net.url;
import java.util.arraylist;
import java.util.list;
 
public class downloadmanager implements runnable {
 // 保存路径
 private string savepath;
 // 总的下载线程数
 private int threadnum;
 // 下载的链接地址
 private string urlfile;
 // 是否下载开始
 private boolean isstarted;
 // 用于监视何时合并文件存放thread的list
 private list downloadlist = new arraylist();
 
 public downloadmanager(string savepath, int threadnum, string urlfile) {
 super();
 this.savepath = savepath;
 this.threadnum = threadnum;
 this.urlfile = urlfile;
 }
 
 // 最终调用线程下载。本线程中调用分线程。
 public void action() {
 new thread(this).start();
 }
 
 public void run() {
 long t1 = system.currenttimemillis();
 system.out.println(t1);
 // 如果没有下载 , 就开始 , 并且将已经下载的变量值设为true
 if (!isstarted) {
 startdownload();
 isstarted = true;
 }
 while (true) {
 // 初始化认为所有线程下载完成,逐个检查
 boolean finish = true;
 // 如果有任何一个没完成,说明下载没完成,不能合并文件
 for (downloadthread thread : downloadlist) {
 if (!thread.isfinish()) {
 finish = false;
 break;
 }
 }
 // 全部下载完成才为真
 if (finish) {
 // 合并文件
 mergefiles();
 // 跳出循环 , 下载结束
 break;
 }
 // 休息一会 , 减少cpu消耗
 try {
 thread.sleep(1000);
 } catch (interruptedexception e) {
 e.printstacktrace();
 }
 }
 long t2 = system.currenttimemillis();
 system.out.println(t2);
 system.out.println("下载用时:"   (t2 -t1));
 }
 
 public void startdownload() {
 // 得到每个线程开始值 , 下载字节数大小
 int[][] posandlength = getposandlength();
 // 根据下载信息创建每个下载线程,并且启动他们。
 for (int i = 0; i < posandlength.length; i  ) {
 int pos = posandlength[i][0];
 int length = posandlength[i][1];
 downloadthread downloadthread = new downloadthread(i   1, length,
 pos, savepath, urlfile);
 new thread(downloadthread).start();
 downloadlist.add(downloadthread);
 }
 }
 
 /**
 * 获得文件大小
 * 
 * @return 文件大小
 */
 public long getfilelength() {
 system.out.println("获得文件大小 start......");
 httpurlconnection conn = null;
 long result = 0;
 try {
 url url = new ;
 conn = (httpurlconnection) url.openconnection();
 // 使用content-length头信息获得文件大小
 result = long.parselong(conn.getheaderfield("content-length"));
 } catch (malformedurlexception e) {
 e.printstacktrace();
 } catch (ioexception e) {
 e.printstacktrace();
 } finally {
 if (conn != null) {
 conn.disconnect();
 }
 }
 system.out.println("获得文件大小 end......"   result);
 return result;
 }
 
 // 具体细节求出每个线程的开始位置和文件下载大小
 public int[][] getposandlength() {
 int[][] result = new int[threadnum][2];
 int filelength = (int) getfilelength();
 int every = filelength % threadnum == 0 ? filelength / threadnum
 : filelength / threadnum   1;
 for (int i = 0; i < result.length; i  ) {
 int length = 0;
 if (i != result.length - 1) {
 length = every;
 } else {
 length = filelength - i * every;
 }
 result[i][0] = i * every;
 result[i][1] = length;
 }
 return result;
 }
 
 // 合并文件
 public void mergefiles() {
 system.out.println("合并文件 start......");
 outputstream out = null;
 try {
 out = new fileoutputstream(savepath);
 for (int i = 1; i <= threadnum; i  ) {
 inputstream in = new fileinputstream(savepath   i);
 byte[] bytes = new byte[2048];
 int read = 0;
 while ((read = in.read(bytes)) != -1) {
 out.write(bytes, 0, read);
 out.flush();
 }
 if (in != null) {
 in.close();
 new file(savepath   i).delete();
 }
 }
 } catch (exception e) {
 e.printstacktrace();
 } finally {
 if (out != null) {
 try {
 out.close();
 } catch (ioexception e) {
 e.printstacktrace();
 }
 }
 }
 system.out.println("合并文件 end......");
 }
 
 public string getsavepath() {
 return savepath;
 }
 
 public void setsavepath(string savepath) {
 this.savepath = savepath;
 }
 
 public int getthreadnum() {
 return threadnum;
 }
 
 public void setthreadnum(int threadnum) {
 this.threadnum = threadnum;
 }
 
 public string geturlfile() {
 return urlfile;
 }
 
 public void seturlfile(string urlfile) {
 this.urlfile = urlfile;
 }
 
 public boolean isstarted() {
 return isstarted;
 }
 
 public void setstarted(boolean isstarted) {
 this.isstarted = isstarted;
 }
 
 public list getdownloadlist() {
 return downloadlist;
 }
 
 public void setdownloadlist(list downloadlist) {
 this.downloadlist = downloadlist;
 }
}

 2、downloadthread类

import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.net.httpurlconnection;
import java.net.url;
 
public class downloadthread implements runnable {
 // 当前第几个线程 , 用于给下载文件起名 file1 file2 file3 ...
 private int whichthread;
 // 监听单一线程下载是否完成
 private boolean isfinish;
 // 本线程要下载的文件字节数
 private int length;
 // 本线程向服务器发送请求时输入流的首位置
 private int startposition;
 // 保存的路径
 private string savepath;
 // 要下载的文件 , 用于创建连接
 private string url;
 
 public void run() {
 httpurlconnection conn = null;
 inputstream in = null;
 outputstream out = null;
 try {
 system.out.println("正在执行的线程:"   whichthread);
 url fileurl = new ;
 // 与服务器创建连接
 conn = (httpurlconnection) fileurl.openconnection();
 // 下载使用get请求
 conn.setrequestmethod("get");
 // 告诉服务器 , 我是火狐 , 不要不让我下载。
 conn.setrequestproperty(
 "user-agent",
 "firefox mozilla/5.0 (windows; u; windows nt 5.1; zh-cn; rv:1.9.1.3) gecko/20090824 firefox/3.5.3");
 // 这里是设置文件输入流的首位置
 conn.setrequestproperty("range", "bytes="   startposition   "-");
 // 与服务器创建连接
 conn.connect();
 // 获得输入流
 in = conn.getinputstream();
 // 在硬盘上创建file1 , file2 , ...这样的文件 , 准备往里面写东西
 out = new fileoutputstream(savepath   whichthread);
 // 用于写入的字节数组
 byte[] bytes = new byte[4096];
 // 一共下载了多少字节
 int count = 0;
 // 单次读取的字节数
 int read = 0;
 while ((read = in.read(bytes)) != -1) {
 // 检查一下是不是下载到了本线程需要的长度
 if (length - count < bytes.length) {
 // 比如说本线程还需要900字节,但是已经读取1000
 // 字节,则用要本线程总下载长度减去
 // 已经下载的长度
 read = length - count;
 }
 // 将准确的字节写入输出流
 out.write(bytes, 0, read);
 // 已经下载的字节数加上本次循环字节数
 count = count   read;
 // 如果下载字节达到本线程所需要字节数,消除循环,
 // 停止下载
 if (count == length) {
 break;
 }
 }
 // 将监视变量设置为true
 isfinish = true;
 } catch (exception e) {
 e.printstacktrace();
 } finally {
 // 最后进行输入、输出、连接的关闭
 if (in != null) {
 try {
 in.close();
 } catch (ioexception e) {
 e.printstacktrace();
 }
 }
 if (out != null) {
 try {
 out.close();
 } catch (ioexception e) {
 e.printstacktrace();
 }
 }
 if (conn != null) {
 conn.disconnect();
 }
 }
 }
 
 public int getstartposition() {
 return startposition;
 }
 
 public void setstartposition(int startposition) {
 this.startposition = startposition;
 }
 
 public string get {
 return url;
 }
 
 public void set {
 this.url = url;
 }
 
 public int getwhichthread() {
 return whichthread;
 }
 
 public void setwhichthread(int whichthread) {
 this.whichthread = whichthread;
 }
 
 public int getlength() {
 return length;
 }
 
 public void setlength(int length) {
 this.length = length;
 }
 
 public string getsavepath() {
 return savepath;
 }
 
 public void setsavepath(string savepath) {
 this.savepath = savepath;
 }
 
 public downloadthread(int whichthread, int length, int startposition,
 string savepath, string url) {
 super();
 this.whichthread = whichthread;
 this.length = length;
 this.startposition = startposition;
 this.savepath = savepath;
 this.url = url;
 }
 
 public downloadthread() {
 super();
 }
 
 public boolean isfinish() {
 return isfinish;
 }
 
 public void setfinish(boolean isfinish) {
 this.isfinish = isfinish;
 }
}

3、testdownload测试类

public class testdownload {
 
 public static void main(string[] args) {
 downloadmanager downloadmanager = new downloadmanager("d:/upload/09018417.zip" , 5 , "http://10.1.2.65:8080/cetvossfront/09018417.zip");
 downloadmanager.action();
 }
}

代码已经测试可以运行!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

声明:本文内容来源于网络,j9九游会老哥俱乐部交流区的版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌j9九游会老哥俱乐部交流区的版权的内容,欢迎发送邮件至:notice#www.elefans.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

网站地图