考虑到列表文件也应该与某些 CPU 需求绑定(bind),我正在尝试在 java 中列出文件时实现超时。以下是代码:
文件列表:
package com.timeout;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileLister implements Runnable{
private String fileLocation;
private List<String> fileList = new ArrayList<String>();
public FileLister(String fileLocation){
this.fileLocation = fileLocation;
}
public void run(){
this.listFiles(this.fileLocation);
}
public void listFiles(String fileLocation){
File file = new File(fileLocation);
File testFile = null;
String[] fileList = file.list();
if(null!=fileList){
for(String fileName:fileList){
testFile = new File(fileLocation+"/"+fileName);
if(testFile.isDirectory()){
listFiles(fileLocation+"/"+fileName);
}else{
synchronized(this){
this.fileList.add(fileLocation+"/"+fileName);
}
}
}
}
}
public List<String> getFileList() {
return fileList;
}
}
计时器:
package com.timeout;
public class Timer implements Runnable{
private long timeout;
public Timer(long timeout){
this.timeout = timeout;
}
public void run(){
long expectedEndTime = System.currentTimeMillis() + this.timeout;
System.out.println("expectedEndTime---"+expectedEndTime);
while(System.currentTimeMillis()<expectedEndTime){
}
System.out.println("endTime---"+System.currentTimeMillis());
System.exit(0);
}
}
调用类:
package com.timeout;
import java.io.IOException;
public class Timeout {
public static void main(String[] args)throws IOException{
FileLister fl = new FileLister("C:/");
Timer tm = new Timer(10000);
Thread flt = new Thread(fl);
Thread tmt = new Thread(tm);
flt.start();
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
System.exit(0);
}
tmt.start();
System.out.println("Files after 11 second--");
for(String fileName:fl.getFileList()){
System.out.println(fileName);
}
}
}
我将超时设置为 11 秒 (10+1)。
这段代码给我一个并发修改异常。考虑到只有一个线程访问 fileList 变量,为什么会发生这种情况。
考虑到列表文件是 IO Bound,定时器会同时工作。
我目前不考虑 TimerTask/Executor。
最佳答案
如果您坚持使用旧的文件 API,这实际上没有任何意义,因为当您 .listFiles()
时,整个 目录条目被吞入数组被退回。之后对其进行迭代不会使目录条目加载“惰性”。
如果您使用新的 java.nio.file API(Java 7+), 有意义的地方是什么?您应该使用它并删除 文件
--,自Files.newDirectoryStream()
确实延迟加载目录条目。 (*)
这将返回一个 DirectoryStream
,它基本上是目录条目上的惰性 Iterable
,除了它还实现了 Closeable
。因此,您可以打断它,例如:
try (
final DirectoryStream<Path> entries = Files.newDirectoryStream(...);
) {
for (final Path entry: entries) {
if (Thread.currentThread().isInterrupted())
break;
// proceed with "entry"
}
}
使用它而不是 .listFiles()
的另一个原因:如果获取 DirectoryStream
的操作失败,您不会得到 null
(!!) 而是一个适当的异常:AccessDeniedException
、NotDirectoryException
、NoSuchFileException
、FileSystemLoopException
(对于文件系统具有符号链接(symbolic link)支持)等。
再次:放弃 File
。
(*):至少对于支持它的操作系统(例如 Linux 有 getdents()
),或者更一般地说,对于支持它的所有 FileSystem
实现
关于java - 在 java 中列出文件时实现超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23102429/