採用多線程的方式實現文件下載

爲了更快的下載資源,我們可以採用多線程的方式來實現文件的下載。

多線程文件下載的基本原理如下:使用HttpURLConnection獲取與資源指定URL的鏈接,httpurlconnection對象通過getContentLength可以獲取下載文件的長度,等到需要下載的文件的長度以後,在本地創建一個與下載文件長度相同的文件,然後通過RandomAccessFile對文件進行寫入操作,那麼如何加入多線程呢?思想是將文件分爲幾個部分,每一個線程完成每一個部分的下載和文件寫入操作。通過RandomAccessFile可以實現文件的隨機訪問,因此每個線程都可以講自己負責下載的內容寫到文件中指定的位置,而不用擔心文件中內容出現錯位。

下面是線程類的代碼

public class MulThreadDownLoad extends Thread {
	
	private String path;
	private File file;
	private  int tasksize;
	private int threadid;
	
	public MulThreadDownLoad(String path ,File file , int tasksize, int threadid){
		this.path = path;   //文件路徑
		this.file = file;	//文件
		this.tasksize = tasksize;	//單個線程的下載量
		this.threadid = threadid;	//線程的id
	}
	@Override
	public void run() {
		try {
			
			int startPoint = threadid * tasksize;     //每條線程寫入文件的起點
			int endPoint = (threadid + 1 ) * tasksize -1 ; //每條線程寫入文件的終點
			
			RandomAccessFile accessFile = new RandomAccessFile(file,"rwd");
			accessFile.seek(startPoint);
			
			HttpURLConnection con = (HttpURLConnection)  new URL(path).openConnection();
			con.setConnectTimeout(500);
			con.setRequestMethod("GET");
		//	con.setRequestProperty("Range", "bytes="+startPoint+"-"+endPoint);  如果設置了Range字段,那麼響應碼是206而不是200
			
			if(con.getResponseCode() == 200){
				
				
				InputStream ins = con.getInputStream();
				ins.skip(startPoint);  //跳過前面線程已經下載過的內容,
				byte [] buffer = new byte [1024];
				int length = 0;
				while((length = ins.read(buffer)) != -1 ){  //將讀取的字節寫入文件中
					accessFile.write(buffer);
				}
				
				accessFile.close();
				ins.close();
			}
			System.out.print((threadid +1 )+"線程已經下載完成 :");
			System.out.println("bytes = "+startPoint+"-"+endPoint);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
	}

}

下面這個是測試類,在測試類中,指定了文件下載的路徑,通過文件的路徑,獲取了文件名

public class MulThreadDownLoadTest {
	
	private File file ;
	
		public static void main(String args []) throws Exception{
		
			String path = "http://localhost:8080/test/jj.jpg";
		
			 new MulThreadDownLoadTest().download(path,3);
		
		}
		/*
		 * @path 指定下載的目標路徑
		 * @threaCount 指定需要多少個線程進行下載
		 */
		public void download(String path, int threadCount ) throws Exception{
		
			URL url = new URL(path);
			HttpURLConnection  con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			con.setConnectTimeout(500);
			if(con.getResponseCode() == 200){
				
				 int ContentLength = con.getContentLength();//獲取響應的長度
				 
				String fileName = getFileName(path); //獲取文件名
				
				file = new File(fileName); 
			
				
				 System.out.println("下載文件大小"+ContentLength);
				RandomAccessFile accessFile = new RandomAccessFile(file,"rwd"); //rwd 表示對文件內容的每個更新都同步寫入到底層存儲設備。 
				accessFile.setLength(ContentLength);
				 accessFile.close();
				
				 //計算每個線程的下載長度爲多少
				 
				 int tasksize = (ContentLength%threadCount == 0 ? ContentLength/threadCount :  ContentLength/threadCount+ 1);
				
				 for(int threadid = 0; threadid < threadCount ;threadid++ ){
					new MulThreadDownLoad(path,file,tasksize,threadid).start();
				}
			}
	}
		
		
		public static   String getFileName(String path){
			
			return  path.substring(path.lastIndexOf("/")+1);
			}
}

 文章參考

傳智播客培訓視頻

http://www.cnblogs.com/tiantianbyconan/archive/2013/02/20/2919132.html





發佈了31 篇原創文章 · 獲贊 31 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章