說明:
生成多個線程去服務(wù)器下載文件,服務(wù)器幾乎同一時間處理每個線程宰睡,這樣就會更快的下好文件,但注意并不是開的線程越多气筋,速度越快拆内。
文件的存儲是有序的,必須保證下載的有序性宠默,我們可以對需要下載的文件進(jìn)行數(shù)據(jù)分塊矛纹,這樣每次訪問的就可以不是完整的文件了。http協(xié)議有一個range字段光稼,可以設(shè)置數(shù)據(jù)訪問的區(qū)域位置或南,java中有RandomAccessfile類可以我們按需要去讀寫改某個區(qū)域。
代碼:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
public class MutiDownload {
private static String DOWNLOAD_PATH="http://s1.music.126.net/download/osx/NeteaseMusic_1.4.3_452_web.dmg";
private static int THREAD_COUNT=3;
private static final String fileName="/Users/August/Desktop/NeteaseMusic_1.4.3_452_web.dmg";
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
HttpURLConnection connection=(HttpURLConnection) new URL(DOWNLOAD_PATH).openConnection();
//設(shè)置參數(shù)艾君,發(fā)送GET請求
connection.setRequestMethod("GET");
//設(shè)置鏈接網(wǎng)絡(luò)的超時時間
connection.setConnectTimeout(8000);
//獲取返回碼
int code =connection.getResponseCode();
if (code==200) {
//代表請求成功
RandomAccessFile raf=new RandomAccessFile(fileName, "rw");
long filesize;
filesize=connection.getContentLength();
long eachsize = filesize/THREAD_COUNT;
raf.setLength(filesize);
raf.close();
for (int i = 0; i < THREAD_COUNT; i++) {
long startIndex=i*eachsize;
long endIndex=(i+1)*eachsize;
if (i==THREAD_COUNT-1) {
endIndex=filesize-1;
}
//開啟線程去服務(wù)器下載
DownloadThread downloadThread=new DownloadThread(DOWNLOAD_PATH,fileName,i,startIndex,endIndex);
}
}else{
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
}
}
}
class DownloadThread extends Thread{
private String url;
private String fileName;
private int threadId;
private long startIndex;
private long endIndex;
private HttpURLConnection connection;
private RandomAccessFile raf;
private InputStream inputStream;
public DownloadThread(String url,String fileName,int threadId,long startIndex,long endIndex) {
this.endIndex=endIndex;
this.fileName=fileName;
this.startIndex=startIndex;
this.threadId=threadId;
this.url=url;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
connection = (HttpURLConnection) new URL(url + "?ts=" + System.currentTimeMillis()).openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
//告訴服務(wù)器每個線程的下載位置與結(jié)束位置
connection.setRequestProperty("RANGE", "bytes=" + startIndex + "-" + endIndex);
int code =connection.getResponseCode();
if (code==206) { //200代表請求全部資源成功采够,206代表請求部分資源成功
inputStream=connection.getInputStream();
raf=new RandomAccessFile(fileName, "rw");
raf.seek(startIndex);//
int len=-1;
long total=0;
byte[]buffer=new byte[1024]; //1kb
while ((len=inputStream.read(buffer))!=-1) {
total+=len;
System.out.println("線程"+threadId+":"+total);
raf.write(buffer,0,len);
}
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
try{
if (connection!=null) {
connection.disconnect();
}
if (raf!=null) {
raf.close();
}
if (inputStream!=null) {
inputStream.close();
}
}catch(Exception e2){
e2.printStackTrace();
}
}
}
}