本文实例为大家分享了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();
}
}
代码已经测试可以运行!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
声明:本文内容来源于网络,九游会下载的版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌九游会下载的版权的内容,欢迎发送邮件至:notice#www.elefans.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。