本文实例为大家分享了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 listdownloadlist = 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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。