首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 多執行緒斷點續傳實現:RandomAccessFile + 配置檔案持久化進度

     編輯:Java 綜合教學

Java 多執行緒斷點續傳實現:RandomAccessFile + 配置檔案持久化進度

大檔案下載/複製若支援斷點續傳,能大幅提升使用者體驗與系統健壯性。本文展示基於 RandomAccessFile 的多執行緒斷點續傳核心實現,關鍵在於每個執行緒獨立維護進度配置檔,重啟時讀取配置恢復斷點。

核心設計思路

  1. 檔案分段:依執行緒數均分檔案大小,計算各執行緒的起始/結束位移。
  2. 隨機存取:使用 RandomAccessFile.seek(position) 定位讀寫指標。
  3. 進度持久化:每個執行緒對應一個 .config 檔,即時寫入當前檔案指標位置。
  4. 斷點恢復:啟動時檢查配置檔,若存在且目標檔案已存在,讀取記錄的指標續傳。
  5. 完成標記:執行緒結束時刪除配置檔,避免重複下載。

測試類:Test.java

package com.dragon.java.multithreaddownload;

import java.io.File;

public class Test {
    public static void main(String[] args) {
        File srcFile = new File("F:/mp4/01_Java.mp4");
        int threadCount = 4;
        
        if (!srcFile.exists()) {
            System.out.println("來源檔案不存在!");
            return;
        }
        
        File desFile = new File(srcFile.getParent(), "new_" + srcFile.getName());
        long partLength = srcFile.length() / threadCount + 1; // 向上取整
        
        for (int i = 1; i <= threadCount; i++) {
            long start = partLength * (i - 1);
            long end = partLength * i;
            new MyThread(srcFile, desFile, start, end).start();
        }
    }
}

執行緒實現:MyThread.java

package com.dragon.java.multithreaddownload;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class MyThread extends Thread {
    private File srcFile, desFile;
    private long start, end;
    
    public MyThread(File srcFile, File desFile, long start, long end) {
        this.srcFile = srcFile;
        this.desFile = desFile;
        this.start = start;
        this.end = end;
    }
    
    @Override
    public void run() {
        // 配置檔:以執行緒 ID 命名,避免衝突
        File configFile = new File(desFile.getParent(), 
            Thread.currentThread().getId() + ".config");
        
        // 若配置檔不存在但目標檔存在,視為已完成
        if (!configFile.exists() && desFile.exists()) {
            System.out.println(getName() + " 已完成下載");
            return;
        }
        
        try (RandomAccessFile rafSrc = new RandomAccessFile(srcFile, "r");
             RandomAccessFile rafDes = new RandomAccessFile(desFile, "rw");
             RandomAccessFile rafConfig = new RandomAccessFile(configFile, "rw")) {
            
            rafConfig.setLength(8); // long 佔 8 bytes
            
            // 讀取上次斷點
            long pointer = rafConfig.readLong();
            if (pointer != 0) {
                start = pointer; // 恢復斷點
            }
            
            rafSrc.seek(start);
            rafDes.seek(start);
            
            System.out.println(getName() + " 已下載:" 
                + ((float) pointer / srcFile.length()) * 100 + "%");
            
            byte[] buffer = new byte[1024]; // 1KB 緩衝區
            int len;
            while ((len = rafSrc.read(buffer)) != -1) {
                rafDes.write(buffer, 0, len);
                pointer = rafSrc.getFilePointer();
                
                // 即時更新配置檔
                rafConfig.seek(0);
                rafConfig.writeLong(pointer);
                
                // 到達本執行緒負責區段結束
                if (pointer >= end) break;
            }
            
        } catch (IOException e) {
            System.err.println(getName() + " 發生異常:" + e.getMessage());
        } finally {
            // 任務完成刪除配置檔
            configFile.delete();
        }
    }
}

關鍵技術點解析

技術點說明
RandomAccessFile支援隨機讀寫,seek() 移動指標,getFilePointer() 獲取當前位置
try-with-resourcesJDK 7+ 自動關閉流,簡化資源管理
配置檔設計單一 long 值儲存指標,極輕量;以執行緒 ID 命名隔離
緩衝區大小建議 1KB~8KB,平衡記憶體與系統呼叫頻率
完成判定配置檔不存在 + 目標檔存在 = 已完成,避免重複工作

擴展建議

  • 新增總進度監聽器,整合各執行緒進度顯示整體百分比
  • 支援 HTTP 範圍請求 (Range header) 實現真正的網路斷點續傳
  • 引入校驗碼 (MD5/SHA256) 驗證檔案完整性
  • 使用 FileChannel + MappedByteBuffer 提升大檔案複製效能
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved