JAVA多線程下載,多線程下載是爲了更多的搶佔服務器的資源,以達到最快的下載速度,但是,不建議開啓過多線程,因爲每臺PC的CPU執行效率都不一樣,如果開啓線程較多,反而會下載的非常慢。
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
public class MulThreadDownload {
private long startTime;
public static void main(String[] args) throws Exception {
System.out.println("開始下載");
String path="http://192.168.1.120:8080/android-studio-bundle-130.677228-windows.exe";
new MulThreadDownload().download(path,2);
}
/**
* 下載文件
* @param path 網絡文件路徑
* @param threadsize 線程數,不建議開啓過多線程。
* @throws Exception
*/
private void download(String path,int threadsize) throws Exception {
startTime=new Date().getTime();//獲取文件開始現在時間
System.out.println("開始時間:"+new Date());
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode()==200){
int length=conn.getContentLength();//獲取網絡文件長度
File file=new File(getFileName(path));//如果不寫路徑則默認存放在項目的根目錄下
RandomAccessFile accessFile=new RandomAccessFile(file, "rwd");//在本地生成一個長度相等的文件
accessFile.setLength(length);//把文件的長度設置的和網絡上文件長度相等
accessFile.close();
//計算每條線程負責下載的數據量
int block=length%threadsize==0 ? length/threadsize :length/threadsize+1;
for (int threadid = 0; threadid < threadsize; threadid++) {
System.out.println("第"+(threadid+1)+"線程下載開始");
new DownloadThread(threadid,block,url,file).start();
}
}else{
System.out.println("下載失敗");
}
}
/**
* 線程類,負責下載操作
*/
private class DownloadThread extends Thread{
private int threadid;//線程ID
private int block;//每條線程負責下載的數據量
private URL url;//線程下載路徑
private File file;//線程下載文件
/**
* 下載線程
* @param threadid 線程ID
* @param block 每條線程負責下載的數據量
* @param url 線程下載的路徑
* @param file 線程下載的文件
*/
public DownloadThread(int threadid, int block, URL url, File file) {
this.threadid=threadid;
this.block=block;
this.url=url;
this.file=file;
}
@Override
public void run() {
int start=threadid*block;//計算該線程從網絡文件的什麼位置開始下載
int end=(threadid+1)*block-1;//下載到網絡文件的什麼位置結束
try{
RandomAccessFile accessFile=new RandomAccessFile(file, "rwd");//在本地生成一個長度相等的文件
accessFile.seek(start);//移動指針到文件的某個位置
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Range","bytes="+start+"-"+end);//指定從網絡上哪個區域開始下載數據
//注意,分段下載的網絡請求返回編碼是206而不是200
if(conn.getResponseCode()==206){
InputStream inStream=conn.getInputStream();
byte[] buffer=new byte[1024];
int len=0;
while((len=inStream.read(buffer))!=-1){
accessFile.write(buffer, 0, len);
}
accessFile.close();
inStream.close();
}
System.out.println("第"+(threadid+1)+"線程已經下載完成");
if((threadid+1)==3){//如果線程下載ID等於最大線程數,說明下載完成,並且獲取當前時間統計下載的總時間
System.out.println("結束時間:"+new Date());
long conutTime=new Date().getTime()-startTime;
System.out.println("下載總耗用時間(毫秒):"+conutTime);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 取得文件名稱
* @param path
* @return
*/
private String getFileName(String path) {
return path.substring(path.lastIndexOf("/")+1);
}
}