import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
public class MutiThreadDownloadTest {
/**
* @param args
*/
public static void main(String[] args) {
String urlString = "http://www.7-zip.org/a/7z920-x64.msi";
String path = "D:\\7z.msi";
try {
new MutiThreadDownloadTest().new MutiThreadDownload(urlString, path, 3).download();
} catch (Exception e) {
e.printStackTrace();
}
}
class MutiThreadDownload {
private String urlString;// 下载路径
private String path;// 文件存储路径
private int threadNum;// 线程数量
private int fileSize;// 文件大小
public MutiThreadDownload(String urlString, String path, int threadNum) {
super();
this.urlString = urlString;
this.path = path;
this.threadNum = threadNum;
}
public void download() throws Exception {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
fileSize = conn.getContentLength();// 获取文件大小
RandomAccessFile destFile = new RandomAccessFile(path, "rw");// 创建空文件
// 设置下载文件相同大小
destFile.setLength(fileSize);
destFile.close();
// 计算每个线程的下载大小
int sizePerThread = fileSize / threadNum;
// 开启线程
for (int i = 0; i < threadNum; i++) {
// 计算每条线程的下载的开始位置
int startPos = i * sizePerThread;// 开始位置
int endPos = sizePerThread * (i + 1) - 1;// 结束位置
new DownloadThread(startPos,endPos,urlString,path).start();
}
destFile.close();
conn = null;
}
}
class DownloadThread extends Thread {
// 定义下载的起始点
private long startPos;
// 定义下载的结束点
private long endPos;
private String urlString;
private String path;
// 构造器,传入输入流,输出流和下载起始点、结束点
public DownloadThread(long startPos, long endPos, String urlString, String path) {
// 输出该线程负责下载的字节位置
System.out.println("startPos="+startPos + " - endPos:" + endPos);
this.startPos = startPos;
this.endPos = endPos;
this.urlString = urlString;
this.path = path;
}
public void run() {
URL url = null;
URLConnection conn = null;
InputStream is = null;
RandomAccessFile out = null;
try {
url = new URL(urlString);
conn = url.openConnection();
is = conn.getInputStream();
byte[] buffer = new byte[1024];
int hasRead = 0;
// 读取网络数据,并写入本地文件
int length = 0;
out = new RandomAccessFile(path, "rw");
is.skip(this.startPos);//流从什么位置读
out.seek(startPos);//文件从什么位置写
// 读取网络数据,并写入本地文件
while (length < endPos - startPos
&& (hasRead = is.read(buffer)) > 0) {
out.write(buffer, 0, hasRead);
// 累计该线程下载的总大小
length += hasRead;
}
System.out.println("线程:" + Thread.currentThread().getId() + "下载完成!");
} catch (Exception ex) {
ex.printStackTrace();
}
// 使用finally块来关闭当前线程的输入流、输出流
finally {
try {
if (out != null) {
out.close();
}
if (is != null) {
is.close();
}
if (conn != null){
conn = null;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}