/**
* 多线程下载器
*/
public class MultiDownloader {
/**
* 开启几个线程从服务器下载数据
*/
public static int threadCount = 3;
public static int runningThreadCount ;
// 服务器的文件,准备出来,tomcat服务器上.
public static String path = "http://192.168.1.104:8080/setup.exe";
// 多线程下载
public static void main(String[] args) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code == 200) {
int length = conn.getContentLength();
System.out.println("服务器文件的长度为:" + length);
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
raf.setLength(length);
raf.close();
int blocksize = length / threadCount;
runningThreadCount = threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId * blocksize;
int endIndex = (threadId + 1) * blocksize - 1;
if (threadId == (threadCount - 1)) {
endIndex = length - 1;
}
new DownloadThread(threadId, startIndex, endIndex).start();
}
}
}
private static class DownloadThread extends Thread {
/**
* 线程id
*/
private int threadId;
/**
* 线程下载的理论开始位置
*/
private int startIndex;
/**
* 线程下载的结束位置
*/
private int endIndex;
/**
* 当前线程下载到文件的那一个位置了.
*/
private int currentPosition;
public DownloadThread(int threadId, int startIndex, int endIndex) {
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
System.out.println(threadId + "号线程下载的范围为:" + startIndex
+ " ~~ " + endIndex);
currentPosition = startIndex;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//检查当前线程是否已经下载过一部分的数据了
File info = new File(threadId+".position");
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
if(info.exists()&&info.length()>0){
FileInputStream fis = new FileInputStream(info);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
currentPosition = Integer.valueOf(br.readLine());
conn.setRequestProperty("Range", "bytes="+currentPosition+"-"+endIndex);
System.out.println("原来有下载进度,从上一次终止的位置继续下载"+"bytes="+currentPosition+"-"+endIndex);
fis.close();
raf.seek(currentPosition);//每个线程写文件的开始位置都是不一样的.
}else{
//告诉服务器 只想下载资源的一部分
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
System.out.println("原来没有有下载进度,新的下载"+ "bytes="+startIndex+"-"+endIndex);
raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.
}
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024*1024*10];
int len = -1;
while((len = is.read(buffer))!=-1){
//把每个线程下载的数据放在自己的空间里面.
// System.out.println("线程:"+threadId+"正在下载:"+new String(buffer));
raf.write(buffer,0, len);
currentPosition+=len;
File file = new File(threadId+".position");
RandomAccessFile fos = new RandomAccessFile(file,"rwd");
//System.out.println("线程:"+threadId+"写到了"+currentPosition);
fos.write(String.valueOf(currentPosition).getBytes());
fos.close();//fileoutstream数据是不一定被写入到底层设备里面的,有可能是存储在缓存里面.
//raf 的 rwd模式,数据是立刻被存储到底层硬盘设备里面.
}
raf.close();
is.close();
System.out.println("线程:"+threadId+"下载完毕了...");
File f = new File(threadId+".position");
f.renameTo(new File(threadId+".position.finish"));
synchronized (MultiDownloader.class) {
runningThreadCount--;
if(runningThreadCount<=0){
for(int i=0;i