0
点赞
收藏
分享

微信扫一扫

java_多线程复制目录(探索)

小云晓云 2022-06-14 阅读 54

这个代码在统计方面是有缺陷的.(线程嵌套)的不良一面

package experiment10.exp1;
/*用多线程的方法实现目录拷贝*/

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Scanner;

public class ThreadsCopy {
static int count = 0;
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
//todo read
System.out.println("输入被复制源目录名:");
String sourceDirectory = scanner.nextLine();

System.out.println("输入副本目标目录名");
String destinationDirectory = scanner.nextLine();

/*调用多线程复制函数*/
long startTime = System.currentTimeMillis();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
copyDir(sourceDirectory, destinationDirectory);
// System.out.println(count+"---");
} catch (IOException e) {
e.printStackTrace();
}
//System.out.println(count+"!!!");
}
});

thread.start();
thread.join();
//System.out.println("共启用了"+count+"个线程");
//todo 这种做法主线程和次线程之间的相对执行顺序还是不明确的(比如主线程对静态变量的打印时机还是不受控的,尽管监视到的累加的最终值是不受影响的.
// 很可能是我对线程嵌套的完整执行的理解不够深刻.;对join的理解不够深刻.
// 目前我认为,线程嵌套的话,新开辟一个线程的语句执行完后,如果没有对应的join来阻塞(直到该线程完整执行完毕才执行下一行代码),那么如果我们想要让嵌套开辟的子线程完全回归,值得每一层配都有join了,如果不都配join,在统计开辟的线程数和运行时间上就比较头疼.
//todo 相应而生的策略:先创建所有需要创建的进程,然后统一start;就解决了线程数的统计问题(统一join,就解决了时间统计的问题)(而且不会退化为单线程排队执行.
/*
Thread threadNew = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("共启用了"+count+"个线程");
}
});
threadNew.start();
threadNew.join();*/
System.out.println("共启用了"+count+"个线程");
System.out.println("目录拷贝完成,共耗时" + (System.currentTimeMillis() - startTime) + "毫秒");
// System.out.println("over!");
}


//todo 多线程嵌套递归的方式复制
/*本递归复制函数具有检查并创建新目录的能力,*/
static void copyDir(String oldPath, String newPath) throws IOException {
System.out.println(count++);//testing(通过中途的内部打印来监视count的累计情况.)

File file = new File(oldPath);
String[] filePath = file.list();/*//当前路径下存在的目录名和文件名的数组.比较建议用list方法,不推荐用listFile方法,因为后面
要通过连接目录名来创建新目录,用字符串比较方便.*/
/*检查新目录是否存在.若不存在,则创建一个*/
if (!(new File(newPath)).exists()) {
(new File(newPath)).mkdir();//创建目录
}
/*遍历当前目录下的子目录和文件*/
// for (int i = 0; i < filePath.length; i++)
for (String x : filePath) {
/*如果这(x)是一个子目录:(执行递归)*/
if ((new File(oldPath + File.separator + x)).isDirectory()) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
copyDir(oldPath + File.separator + x, newPath + File.separator + x);
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();

}

/*如果x所指的是个文件:执行复制即可*/
if (new File(oldPath + File.separator + x).isFile()) {
File source = new File(oldPath + File.separator + x);
File dest = new File(newPath + File.separator + x);
if (!(dest.exists())) {
Files.copy(source.toPath(), dest.toPath());//创建新文件的能力
}

}
}//endFor
//System.out.println("The replication operation has been successfully executed!");
}//endCopyFunction
}

继续修改

package experiment10.exp1;

import experiment9.FileName;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
* @Author xuchaoxin
* @Date 12/19/2020 9:41 AM
* @Version 1.0
*/
public class CreatCopyPathThreads {

/*本递归复制函数具有检查并创建新目录的能力,*/

/**
* @param srcPath 可能是个目录,也可能是个文件
* @param desPath 当srcPath 是一个目录的时候,desPath也必须是一个目录(1.约定该参数和srcPath是相同尾缀时;2.不用关心尾缀
* 可能的参数组合包括:dir->dir;file->file;file->dir;(不可能是dir->file)
* @throws IOException
* @throws InterruptedException
*/
static void copyPath(String srcPath, String desPath) throws IOException, InterruptedException {
// System.out.println(count++);//testing(通过中途的内部打印来监视count的累计情况.)
File srcPathFile = new File(srcPath);
File desFile = new File(desPath);
/* 如果源目标是个目录,则要保证目标目录存在: */
// if (srcPathFile.isDirectory()&&!(new File(desPath)).exists()) {
// (new File(desPath)).mkdir();//创建目录
// }
/*分析源路径*/
if (srcPathFile.isDirectory()) {
if (!(new File(desPath)).exists()) {
desFile.mkdir();//创建目录
}
/*遍历当前目录下的子目录和文件(即各个条目)*/
String[] filesPathString = srcPathFile.list();
for (String subItem : filesPathString) {

String absoluteSrcSubItemStr = srcPath + File.separator + subItem;
String absoluteDesSubItemStr = desPath + File.separator + subItem;


/*直接递归:*/
copyPath(absoluteSrcSubItemStr, absoluteDesSubItemStr);
}//endFor

}//end if
else {
if (!desFile.exists()) {
Files.copy(srcPathFile.toPath(), desFile.toPath());
}
}

//test the class
public static void main(String[] args) {
try {
//计时开始.
long startTime = System.currentTimeMillis();
copyPath(FileName.fileName11_1, "D://src");
System.out.println("单线程目录拷贝完成,共耗时" + (System.currentTimeMillis() - startTime) + "毫秒");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}


}//end class


举报

相关推荐

0 条评论