jAVA基礎 提高文件複製性能之多線程複製文件
利用IO流中的隨機訪問文件 RandomAccessFile 和文件通道 FileChanne 複製文件可大大提高文件的讀寫效率,在此基礎上利用多線程複製文件使其性能更優。因線程的個數可根據文件的大小及需求而定。其大概原理是根據給定的線程個數,將文件分段,每個線程負責的數據大小=文件長度/線程個數,將不能除盡的部分留給最後一段文件所分配的線程處理。以下是實現代碼及自己理解的註釋,多有偏差請見諒。下面是兄弟連java培訓總結的一些代碼:供參考。
程序實現類代碼:
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
//定義一個CopyThread類繼承Thread類
public class CopyThread extends Thread{
private String srcPath;//原文件地址
private String destPath;//目標文件地址
private int start, end;//start指定起始位置,end指定結束位置
//構造CopyThread方法
public CopyThread(String srcPath, String destPath, int start, int end) {
this.srcPath = srcPath;//要複製的源文件路徑
this.destPath = destPath;//複製到的文件路徑
this.start = start;//複製起始位置
this.end = end;//複製結束位置
}
//重寫run()方法
public void run() {
try {
//創建一個只讀的隨機訪問文件
RandomAccessFile in = new RandomAccessFile(srcPath, "r");
//創建一個可讀可寫的隨機訪問文件
RandomAccessFile out = new RandomAccessFile(destPath, "rw");
in.seek(start);// 將輸入跳轉到指定位置
out.seek(start);// 從指定位置開始寫
FileChannel inChannel = in.getChannel(); //文件輸入通道
FileChannel outChannel = out.getChannel();//文件輸出通道
//鎖住需要操作的區域,false代表鎖住
FileLock lock = outChannel.lock(start, (end-start), false);
//將字節從此通道的文件傳輸到給定的可寫入字節的outChannel通道。
inChannel.transferTo(start, (end-start), outChannel);
lock.release();//釋放鎖
out.close();//從裏到外關閉文件
in.close();//關閉文件
} catch (Exception e) {
e.printStackTrace();
}
}
}
測試類代碼:
import java.io.File;
public class TestMain {
public static void main(String[] args) {
//要複製的源文件路徑
String srcPath = "F:\\sun\\上課筆記\\aa.txt";
String destPath = "F:\\sun\\上課筆記\\aa復件.txt";
// 獲得源文件長度
File f = new File(srcPath);
long len = f.length();
int count = 3;// 需要的線程數
int oneNum = (int) (len / count);//每個線程負責的文件長度,強制轉換成int類型
//用for循環處理劃分文件的第一部分跟第二部分(循環次數可根據定義的線程數調整)
for (int i = 0; i < count - 1; i++) {
//oneNum * i 起始位置, oneNum * (i + 1)要複製數據的長度
CopyThread ct = new CopyThread(srcPath, destPath, oneNum * i,oneNum * (i + 1));
ct.start();
}
//文件長度不能整除的部分放到最後一段處理
CopyThread ct = new CopyThread(srcPath, destPath, oneNum * (count-1),(int)len);
ct.start();
}
}