/**
* 多線程下載器
*/
public class MultiDownloader {
/**
* 開啟幾個線程從服務(wù)器下載數(shù)據(jù)
*/
public static int threadCount = 3;
public static int runningThreadCount ;
// 服務(wù)器的文件,準(zhǔn)備出來,tomcat服務(wù)器上.
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("服務(wù)器文件的長度為:" + 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;
/**
* 線程下載的結(jié)束位置
*/
private int endIndex;
/**
* 當(dāng)前線程下載到文件的那一個位置了.
*/
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();
//檢查當(dāng)前線程是否已經(jīng)下載過一部分的數(shù)據(jù)了
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("原來有下載進(jìn)度,從上一次終止的位置繼續(xù)下載"+"bytes="+currentPosition+"-"+endIndex);
fis.close();
raf.seek(currentPosition);//每個線程寫文件的開始位置都是不一樣的.
}else{
//告訴服務(wù)器 只想下載資源的一部分
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
System.out.println("原來沒有有下載進(jìn)度,新的下載"+ "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){
//把每個線程下載的數(shù)據(jù)放在自己的空間里面.
// 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數(shù)據(jù)是不一定被寫入到底層設(shè)備里面的,有可能是存儲在緩存里面.
//raf 的 rwd模式,數(shù)據(jù)是立刻被存儲到底層硬盤設(shè)備里面.
}
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