将一个文件分为四个部分,采用多线程模拟下载。
public class Test3Download {
public static void main(String[] args) {
int fileLength = 0;
// 1 创建文件对象
File file = new File("C:\\123.mp4");
// 2 拿到文件的长度
if (file.exists()) {
fileLength = (int) file.length();
}
// 拿到每个线程需要执行的长度
int length = fileLength % 4 == 0 ? fileLength / 4 : fileLength / 4 + 1;
// 如果 取余4 不等于0 每一个就多读取一个字节
// 算一下最后一个需要读取的长度
// 最后一块的长度
int lastLength = fileLength - length * 3;
// 启动线程
DownLoad l1 = new DownLoad(0, length);// 26 0-25
DownLoad l2 = new DownLoad(length, length);// 26-52 第一个lenth 起点
// 第二个lenght 长度
DownLoad l3 = new DownLoad(2 * length, length);
DownLoad l4 = new DownLoad(3 * length, lastLength);
// 启动线程
l1.start();
l2.start();
l3.start();
l4.start();
}
}
class DownLoad extends Thread {
// 需要什么? 需要确定开始的位置 和 读取的长度
private int start;
private int length;
public DownLoad(int start, int length) {
super();
this.start = start;
this.length = length;
}
@Override
public void run() {
// 随机读写流
// 注意: 一个随机读写流不能同时去读和写,想要读和写,那就创建两个随机读写流对象
RandomAccessFile read = null;
RandomAccessFile write = null;
try {
System.out.println(Thread.currentThread().getName() + "开始复制...");
read = new RandomAccessFile("C:\\123.mp4", "rw");
write = new RandomAccessFile("D:\\1234.mp4", "rw");
// 跳过指定的位置
read.seek(start);
write.seek(start); // 重点标注
// 读取 数组的长度和需要读取的数据相同
byte[] b = new byte[4096];
int len = 0;
int i = 0;
while (true) {
if (length - i < b.length) {
read.read(b, 0, length - i);
write.write(b, 0, length - i);
break;
} else {
len = read.read(b);
i += len;
write.write(b, 0, len);
}
}
System.out.println(Thread.currentThread().getName() + "复制完成");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (read != null) {
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (write != null) {
try {
write.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}