每個文件啟用多線程斷點下載(如 4 線程/文件),同時下載 10 個文件即產生 40 線程,導致 OOM、CPU 抖動、網絡擁塞。
| 方案 | 核心思想 | 優點 | 缺點 |
|---|---|---|---|
| 固定線程池 | ExecutorService pool = Executors.newFixedThreadPool(MAX_THREADS); 所有下載任務提交到同一池 | 實現簡單,線程數可控,復用線程減少創建開銷 | 長任務佔用核心線程導致短任務排隊,需區分 IO/CPU 密集型 |
| 自定義任務隊列 | 維護 BlockingQueue<DownloadTask>,單一調度線程按優先級/順序分發到工作線程組 | 靈活控制並發策略(如同一文件分片串行、不同文件並行)、支持暫停/恢復/取消 | 代碼量較大,需自行處理線程生命週期、異常重試 |
| 成熟框架 | OkHttp + Dispatcher / RxJava / Kotlin Coroutines / WorkManager | 生產級可靠性,內建連接池、重試、背壓、生命週期感知 | 引入依賴,學習曲線 |
// 單例 OkHttpClient,共享連接池與調度器
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(new Dispatcher(Executors.newFixedThreadPool(8))) // 全局最大 8 並發
.build();
// 下載任務封裝
class DownloadTask implements Runnable {
String url; File dest; long startByte; long endByte;
// 實現 Range 請求、隨機訪問寫入、進度回調、校驗
}
// 前台/後台服務統一提交
executor.submit(new DownloadTask(...));
Range: bytes=start-end + RandomAccessFile.seek(start) 寫入。ConnectivityManager 切換網絡時暫停非 WiFi 任務。