實現多執行緒下載同一個檔案
阿新 • • 發佈:2019-02-17
原理:
示例程式碼:
public class LoadFile { private static int threadCount = 3;// 下載的執行緒數量 public static void main(String[] args) { // 1、與伺服器建立連線,獲得檔案的大小,在本地建立一個與需下載檔案同等大小的臨時檔案 String path = "http://localhost/safe.exe"; try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); int code = conn.getResponseCode(); if(200 == code) { // 獲得檔案的長度 int length = conn.getContentLength(); System.out.println("檔案總長度為:"+length); // 在本地建立一個可以隨機讀取的與原始檔同等大小的臨時檔案 RandomAccessFile raf = new RandomAccessFile("safe.exe", "rwd"); // 指定檔案的長度 raf.setLength(length);// 設定檔案長度 raf.close(); // 2、實現多執行緒下載資源 int blockSize = length / threadCount ;// 每個執行緒平均需要下載檔案的大小 for(int threadId = 1; threadId <= threadCount; threadId++) { // 每個執行緒下載檔案的初始位置和結束位置 int startIndex = (threadId-1) * blockSize; int endIndex = threadId * blockSize - 1; // 下載的最後一塊的情況 if(threadCount == threadId) { endIndex = length - 1;// 如果不減1的話,就超出了檔案的範圍 } System.out.println("執行緒 "+threadId+"下載位置為:"+startIndex+"--->"+endIndex); // 啟動下載執行緒 new DownloadThread(path, startIndex, endIndex, threadId).start(); } } else { System.out.println("伺服器出現錯誤"); } } catch (Exception e) { System.out.println("連線伺服器URL出現錯誤"); e.printStackTrace(); } } }
public class DownloadThread extends Thread { private String path;// 伺服器路徑 private int startIndex;// 塊檔案開始位置 private int endIndex;// 快檔案結束位置 private int threadId;// 執行緒編號 public DownloadThread() { } public DownloadThread(String path, int startIndex, int endIndex, int threadId) { this.path = path; this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); // 提交請求可以從指定位置讀取檔案 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); int code = conn.getResponseCode(); // 請求全部檔案成功返回200, 請求部分檔案成功返回206 if (206 == code) { RandomAccessFile raf = new RandomAccessFile("safe.exe", "rwd"); // 隨機檔案從哪裡讀 raf.seek(startIndex);// 定位檔案 InputStream is = conn.getInputStream(); 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 + "下載完畢!!!!"); } else { System.out.println("執行緒"+threadId+"請求的部分資源失敗"); } } catch (Exception e) { System.out.println("下載執行緒的URL連線異常"); e.printStackTrace(); } } }
// 別下載太大的檔案,可能等待時間很長
/*Output:
檔案總長度為:11556608
執行緒 1下載位置為:0--->3852201
執行緒 2下載位置為:3852202--->7704403
執行緒 3下載位置為:7704404--->11556607
執行緒2下載完畢!!!!
執行緒1下載完畢!!!!
執行緒3下載完畢!!!!
*/