问题:利用子线程完成一个较大文件的拷贝。
由于文件过大,如果只用主线程进行拷贝,会比较慢,所以我们可以利用多个子线程进行文件的拷贝,将文件划分成小块,减少一个线程的工作量,提高了CPU的利用率,从而提高了工作效率。
具体问题分析如下:
假设文件的大小为4G,我们需要4个线程并发进行对文件的拷贝,有以下的问题需要解决:
1、每个线程所拷贝的文件的大小(如何划分)
2、每个子线程的拷贝起始位置的定位
3、拷贝文件的方式(所选取的流)
设计方案
子线程:
选取RandomAccessFile流,因为它支持读取和写入随机访问文件,其中的seek()方法可以将指针移到固定位置,将读取的内容写入目的文件
class MyThread extends Thread{
private String srcPath;
private String dextPath;
private long startIndex;
private long endIndex;
//构造函数子线程 4个参数:起始位置,终止位置,源地址,目的地址
public MyThread(String srcPath,String dextPath,long startIndex,long endIndex){
this.srcPath = srcPath;
this.dextPath = dextPath;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
RandomAccessFile src = new RandomAccessFile(srcPath,"r");
RandomAccessFile dest = new RandomAccessFile(dextPath, "rw");
//使文件移动到指定文件
src.seek(startIndex);
dest.seek(startIndex);
long index = startIndex;
byte[]bytes = new byte[1024];
int n;
while ((n = src.read(bytes))!=-1){
index += n;
dest.write(bytes,0,n);
if (index >= endIndex){
break;
}
}
src.close();
dest.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
功能函数:
里面包括了主线程,它的主要作用就是划分子线程的读取范围(假设是4个子线程共同拷贝4G的文件)
*第一个线程读取0-1G: 0-length
*第二个线程读取1G-2G: length+1…2length
*第三个线程读取2G-3G: 2length…3length
*第四个线程读取3G-4G: 3length…file.length(处理直到文件结尾的内容)
public static void MutilThreadCopyFile(String srcPath, String destPath, Integer ThreadNum) throws FileNotFoundException {
//参数校验,判断文件是否为空,线程数是否不合格
if (srcPath == null || destPath == null || ThreadNum < 1) {
System.out.println("输入有误,无法执行!");
}
//文件的划分
File file = new File(srcPath);
//文件的长度
long fileLenght = file.length();
long subTLength = fileLenght / ThreadNum;//每个线程需要处理的数据量
//主线程处理,将文件分给子线程,让子线程进行处理
for (int i = 0; i < ThreadNum - 1; i++) {
MyXianCheng myXianCheng = new MyXianCheng(srcPath, destPath, i * subTLength, (i + 1) * subTLength);
myXianCheng.start();
}
//将剩余部分全部交给最后一个线程处理
MyXianCheng myXianCheng = new MyXianCheng(srcPath, destPath, ThreadNum * subTLength, 1 * fileLenght);
myXianCheng.start();
}
主函数:
* srcPath:源路径
* destPath:目标地址
* ThreadNum:线程数量
public static void main(String[] args) throws FileNotFoundException {
String srcPath = "D:\\1.txt";
String dsetPath = "D:\\2.txt";
System.out.println("请输入需要的子线程个数。");
Scanner sc = new Scanner(System.in);
Integer n = sc.nextInt();
System.out.println("文件开始拷贝……");
MutilThreadCopyFile(srcPath,dsetPath,n);
new Thread().start();
System.out.println("文件拷贝结束……");
}
运行展示:
源文件:1.txt
目标文件:2.txt