题目
使用多个线程来复制文件
分析
多线程复制需要使用随机访问流 RandomAccessFile 中的指针来确定每个线程复制文件的起始位置
先确定线程数量,再讲文件大小按线程数量进行均分,如果有多处就在创建一个线程来复制剩余的字节数
注意:使用字节数组缓冲池来复制文件,会导致每个线程复制到最后剩余不到一个缓冲池大小如果被其他线程抢到,那么再次抢到的时候会复制整个缓冲池大小的文件,不过最后会被覆盖掉,文件复制成功
程序代码
package com.company.deno;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class MyDemo {
public static void main(String[] args) throws FileNotFoundException {
//封装源文件
File file = new File("E:\\video.mp4");
long totalLength = file.length();
//定义线程的数量
long threadNum = 3;
//平均每个线程复制的字节数
long pjLength = totalLength / threadNum;
for (long i = 0; i < threadNum; i++) {
//每个线程的开始字节位置,和结束位置
long start = i * pjLength;
long end = (i + 1) * pjLength;
//开启线程
new CopyThread(start, end, "E:\\video.mp4", "D:\\video.mp4").start();
}
//如果不够均分,我就补一个线程,复制剩余的字节
long yu = totalLength % threadNum;
if (yu != 0) {
long start = threadNum * pjLength;
long end = totalLength;
//开启线程 不能均分补一个线程
new CopyThread(start, end, "E:\\video.mp4", "D:\\video.mp4").start();
}
}
}
class CopyThread extends Thread {
long start;
long end;
RandomAccessFile in = null;
RandomAccessFile out = null;
// start 复制的起始位置
//end 复制的结束位置
//srcFile 源文件路径
//targetFile 目标文件路径
public CopyThread(long start, long end, String srcFile, String targetFile) throws FileNotFoundException {
this.start = start;
this.end = end;
in = new RandomAccessFile(srcFile, "rw");
out = new RandomAccessFile(targetFile, "rw");
}
@Override
public void run() {
//复制文件逻辑
try {
//设置指针位置
in.seek(start);
out.seek(start);
int len = 0;
byte[] bytes = new byte[1024 * 8];
while (start < end && (len = in.read(bytes)) != -1) {
start += len;//记录每次复制的字节数
out.write(bytes, 0, len);
}
//释放资源
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
文件复制成功