1.问题描述
实现功能:使用@Schedule注解定时多线程清理ftp文件
产生问题:未知原因莫名清空ftp连接的主目录下全部文件
2.问题解决
1.查看delete方法调用
idea环境,右键find usage 查看是否有其他地方调用ftp删除方法,结果没有其他调用。
2.单步调试
打断点单步调试,结果还是莫名删除文件,删除时间随机,调试找不到原因
3.打印日志
在类初始化,方法调用,线程执行等地加日志,结果发现日志重复输出,由于定时器@Schedule重复执行,所以导致ftp文件被清空。定时器重复执行是因为类被重复初始化,由于springmvc配置问题重复扫描@component,修改配置后解决。由于清空文件的bug太严重,为保证线程安全,加同步。
3.总结
1.ftp方法没问题,不要过多质疑三方库。
2.打日志和调试都很有效,多线程、并行并发等情况打日志优先。
3.多写日志,好的程序,应该看日志就能对它的运作细节了如指掌
附录代码
求取ftp文件大小(层次遍历)
注:尽量少用递归,递归可能栈溢出
// 递归方式获取文件大小,递归可能栈溢出
public long getFileSizeByRecur(FTPClient ftpClient,FTPFile ftpFile) throws IOException {
long size=0;
if (ftpFile.isDirectory()) {
ftpClient.changeWorkingDirectory(ftpFile.getName());
for (FTPFile file : ftpClient.listFiles()) {
size += getFileSizeByRecur(ftpClient,file);
}
ftpClient.changeToParentDirectory();
} else {
size += ftpFile.getSize();
}
return size;
}
// 层次遍历获取文件大小
public long getFileSizeByLevel(FTPClient ftpClient,FTPFile ftpFile)throws IOException{
List<FTPFile> list=new ArrayList<>();
long size = 0;
list.add(ftpFile);
for (int i=0;i<list.size();i++){
if (list.get(i).isDirectory()){
ftpClient.changeWorkingDirectory(list.get(i).getName());
list.addAll(Arrays.asList(ftpClient.listFiles()));
ftpClient.changeToParentDirectory();
}else{
size+=list.get(i).getSize();
}
}
list.clear(); // 防止内存泄露
return size;
}
网友评论