Java多線程文件復制功能
這里講解一個利用Java里面的RandomAccessFile
流來實現多線程文件的快速復制功能。
新建一個線程類:
class BpTransf extends Thread {
private File srcFile = null;
private File dstFile = null;
private long posStart;
private long posEnd;
/** * 線程類的構造方法 * * @param srcFile * 源文件 * @param dstFile * 目標文件 * @param posStart * 復制起點位置 * @param posEnd * 復制終點位置 * @throws IOException */
public BpTransf(File srcFile, File dstFile, long posStart, long posEnd) throws IOException {
this.srcFile = srcFile;
this.dstFile = dstFile;
if (!dstFile.exists()) {
dstFile.createNewFile();
}
this.posStart = posStart;
this.posEnd = posEnd;
}
@Override
public void run() {
RandomAccessFile rafWrite = null;
RandomAccessFile rafRead = null;
try {
rafWrite = new RandomAccessFile(dstFile, "rw");
rafRead = new RandomAccessFile(srcFile, "r");
} catch (FileNotFoundException e) {
System.out.println("沒有找到文件!");
}
byte[] b = new byte[1024 * 8];// 定義存儲數據的字節數組
int len = 0;
try {
rafWrite.seek(posStart);// 設置寫文件指針的起點
rafRead.seek(posStart);// 設置讀文件指針的起點
while ((len = rafRead.read(b)) != -1) {
rafWrite.write(b, 0, len);
// 如果文件指針比復制終點位置都大則說明此段復制完畢,可停止復制
if (rafWrite.getFilePointer() >= posEnd) {
// 若復制完畢則提示該線程復制完畢
System.out.println(this.getName() + "讀取完畢!");
break;
}
}
rafWrite.close();
rafRead.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
利用上面的線程類來復制文件
/** * 多線程復制文件 * */
public class ThreadsBpTransf {
public static void main(String[] args) throws IOException {
long startTime=System.currentTimeMillis();
File srcFile = new File("src.mp4");// 源文件
File dstFile = new File("dst.mp4");// 目標文件
long srcSize = srcFile.length();// 源文件長度
int threadCount = 8;// 線程數量
// 因為讀取源文件時的字節數組大小設置為1024*8所以這里將每個線程復制的長度設定為1024*8的整數倍
long avg = (srcSize / threadCount) / (1024 * 8) * 1024 * 8;// 將平均值轉換為1024*8的倍數
BpTransf[] bp = new BpTransf[threadCount];// 新建線程數組
// 若源文件不存在則提示並返回
if (!srcFile.exists()) {
System.out.println("源文件不存在。");
return;
}
for (int i = 0; i < threadCount; i++) {
// 如果是最后一個線程則需要讀取末尾所有字節,不是最后一個線程則按照1024*8的倍數分配空間
if (i == threadCount - 1) {
bp[i] = new BpTransf(srcFile, dstFile, i * avg, srcSize);
} else {
bp[i] = new BpTransf(srcFile, dstFile, i * avg, (i + 1) * avg);
}
// 分配每個線程需要讀取字節的長度
bp[i].start();// 啟動線程
}
for (BpTransf bpTransf : bp) {
try {
bpTransf.join();// 判斷線程是否復制完畢
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("程序運行完畢。");// 提示程序運行完畢
// 輸出文件前后復制大小
System.out.println("源文件大小" + srcFile.length() + "" + ",復制后的文件大小:" + dstFile.length());
long time=System.currentTimeMillis()-startTime;
System.out.println("復制用時"+time/1000+"s");
}
}