多執行緒下的下載原理

never123450發表於2014-05-11
 *1.本地建立一個大小跟伺服器檔案相同大小的臨時檔案
 *2.計算分配幾個執行緒去下載伺服器上的資源,知道每個執行緒下載的位置
 *3.開啟多(3)個執行緒,沒個執行緒下載對於位置的檔案

 *4.如果所有的執行緒,都把自己的資料下載完畢了,伺服器上的資源就被下載到本地


import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.RandomAccess;


/**
 * 多執行緒下載的測試類
 * @author Administrator
 *
 */
public class Demo1 {

	public static int threadcount = 3;
	public static void main(String[] args) throws Exception{
		//1.連線伺服器,獲取一個檔案獲取檔案的長度,在本地建立一個大小跟伺服器檔案一樣大的臨時檔案
		String path = "http://192.168.1.100:8080/360.exe";
		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("setup.exe","rwd");
			//指定建立的這個檔案的長度
			raf.setLength(length);
			raf.close();
			
			//假設是3個執行緒去下載資源
			//平均每一個執行緒下載的檔案的大小
			int blockSize = length / threadcount;
			for (int threadId = 1; threadId < threadcount; threadId++) {
				//第一個執行緒下載的開始位置
				int startIndex = (threadId-1)*blockSize;
				int endIndex = threadId*blockSize - 1;
				if(threadId==threadcount){//最後一個執行緒下載的長度要稍微長一點
					
					endIndex = length;
				}
				System.out.println("執行緒:" + threadId + "下載:" + startIndex + "-->" + endIndex);
				new DownloadThread(endIndex,threadId,startIndex,path).start();
			}
		}else {
			System.out.println("伺服器錯誤");
		}
		
	}
	
	/**
	 * 下載檔案的子執行緒下載對應位置的檔案
	 * @author Administrator
	 *
	 */
	public static class DownloadThread extends Thread{
		private int threadId;
		private int startIndex;
		private int endIndex;
		private String path;
		
		/**
		 * @param path 下載檔案在伺服器上的路徑
		 * @param threadId 執行緒id
		 * @param startIndex 執行緒下載的開始位置
		 * @param endIndex 執行緒下載的結束位置
		 */
		public DownloadThread(int threadId, int startIndex, int endIndex,String path) {
			this.path = path;
			this.threadId = threadId;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}


		public void run() {
			try {
				URL URL = new URL(path);
				HttpURLConnection connection = (HttpURLConnection) URL.openConnection();
				connection.setRequestMethod("GET");
				//重要:請求伺服器下載部分的檔案指定的位置
				connection.setRequestProperty("Range","bytes="+startIndex +"-" + endIndex);
				connection.setConnectTimeout(5000);
				int code = connection.getResponseCode();//從伺服器請求全部資源,如果產品能夠伺服器請求部分資源,206 ok
				System.out.println("code:"+code);
				InputStream is = connection.getInputStream();//已經設定了 請求的位置,返回的是當前位置對於的檔案輸入流
				RandomAccessFile raf = new RandomAccessFile("setup.exe","rwd");
				//隨機寫檔案的時候從哪個位置開始寫
				raf.seek(startIndex);//定位檔案
				
				int len = 0;
				byte[] buffer = new byte[1024];
				while ((len=is.read(buffer))!=-1) {
					raf.write(buffer,0,len);
					
				}
				is.close();
				raf.close();
				System.out.println("執行緒:"+threadId+"下載玩完畢");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}


相關文章