Android核心技術-day05-04-JavaSE多執行緒下載
阿新 • • 發佈:2018-11-07
package com.gaozewen.lib; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MultiDownloader { public static final String path = "http://192.168.1.102:8080/xunlei.exe"; public static final int TOTAL_THREAD_COUNT = 3; public static int runningThreadCount = 0; public static void main(String[] args) { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { int length = conn.getContentLength(); System.out.println("file length: " + length); // 建立一個空的檔案,並且設定他的檔案長度等於伺服器上的檔案長度 RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); raf.setLength(length); raf.close(); int blockSize = length / TOTAL_THREAD_COUNT; System.out.println("every block size: " + blockSize); runningThreadCount = TOTAL_THREAD_COUNT; for (int threadId = 0; threadId < TOTAL_THREAD_COUNT; threadId++) { int startPosition = blockSize * threadId; int endPosition = blockSize * (threadId + 1) - 1; // -1 是到當前塊的最後一個位元組 if (threadId == (TOTAL_THREAD_COUNT - 1)) { endPosition = length - 1; } System.out.println(String.format("threadId: %s\ndownload rage: %s to %s", threadId, startPosition, endPosition)); new DownloadThread(threadId, startPosition, endPosition).start(); } } else { } } catch (Exception e) { e.printStackTrace(); } } /** * 從網路路徑獲取檔名 * * @param path 網路路徑 * @return 檔名 */ private static String getDownloadFileName(String path) { return path.substring(path.lastIndexOf("/") + 1); } /** * 下載檔案的執行緒 */ private static class DownloadThread extends Thread { /** * 執行緒 id */ private int threadId; /** * 當前執行緒下載的起始位置 */ private int startPosition; /** * 當前執行緒下載的終止位置 */ private int endPosition; public DownloadThread(int threadId, int startPosition, int endPosition) { this.threadId = threadId; this.startPosition = startPosition; this.endPosition = endPosition; } @Override public void run() { System.out.println(String.format("threadID: %s begin working", threadId)); // lest thread download it's self range data try { // 查詢 記錄斷點資訊的檔案 File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt"); if (finfo.exists() && finfo.length() > 0) { // 斷點下載 FileInputStream fis = new FileInputStream(finfo); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String lastPosition = br.readLine(); // This thread download data before times; startPosition = Integer.parseInt(lastPosition); fis.close(); } // 第一次下載 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); System.out.println(String.format("begin and end: %s range of download: %s to %s", threadId, startPosition, endPosition)); conn.setRequestProperty("Range", String.format("bytes=%s-%s", startPosition, endPosition)); // 從伺服器下載資源 int code = conn.getResponseCode(); if (code == 206) { InputStream is = conn.getInputStream(); // 第一次沒有這個檔案則建立,下次直接開啟這個檔案 RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); // !!! position of begin to write raf.seek(startPosition); byte[] buffer = new byte[1024]; int len = -1; int total = 0; // 當前執行緒 這次下載的資料 while ((len = is.read(buffer)) != -1) { raf.write(buffer,0,len); total += len; // 建立記錄 儲存當前執行緒下載的位置 (注意: rwd 同步實時寫入到裝置中) RandomAccessFile infoRaf = new RandomAccessFile(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt","rwd"); infoRaf.write(String.valueOf(startPosition + total).getBytes()); infoRaf.close(); } raf.close(); is.close(); System.out.println(String.format("thread: %s download complete...",threadId)); }else { System.out.println("request download failed"); } } catch (Exception e) { e.printStackTrace(); }finally { synchronized (MultiDownloader.class){ runningThreadCount--; if(runningThreadCount <= 0){ // 多執行緒下載完成 刪除 位置資訊檔案 System.out.println("multi thread download complete."); for (int i = 0; i < TOTAL_THREAD_COUNT; i++) { File positionFile = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + i + ".txt"); // System.out.println(positionFile.delete()); } } } } } } }