java - 在 java 中列出文件时实现超时

标签 java multithreading

考虑到列表文件也应该与某些 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)。

  1. 这段代码给我一个并发修改异常。考虑到只有一个线程访问 fileList 变量,为什么会发生这种情况。

  2. 考虑到列表文件是 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 (!!) 而是一个适当的异常:AccessDeniedExceptionNotDirectoryExceptionNoSuchFileExceptionFileSystemLoopException(对于文件系统具有符号链接(symbolic link)支持)等。

再次:放弃 File

(*):至少对于支持它的操作系统(例如 Linux 有 getdents()),或者更一般地说,对于支持它的所有 FileSystem 实现

关于java - 在 java 中列出文件时实现超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23102429/

相关文章:

java - Spring MVC : @PathVariable form

java - Idea Intellij拆箱警告似乎不是基于数据流分析

java - 一个方法依赖于类中的另一个方法

java - Spring TaskExecutor 实现

c - 线程间setjmp/longjmp处理超时

java - 树莓派启动时无法执行java程序

java - 两个服务器实例上的 Hibernate 主键冲突

java - Android Studio 构建错误 : "Content is not allowed in prolog."

java - OutOfMemoryError 会导致线程死亡吗?

c++ - 有人可以解释为什么使用 OpenMP 部分比单线程运行得慢吗?