Java nio:使用DirectoryStream进行多线程处理

时间:2016-07-12 20:54:59

标签: java multithreading nio

我有一个难以复制的错误,其中一个线程挂起。

  • 网络蜘蛛线程将html文件转储到目录中。
  • 文件处理线程读取目录中的文件进程 他们一个接一个地移动它们。

由于文件处理器移动文件(按逻辑必要性)只能在文件已经在目录中时发生,因此文件处理器文件读取过程是异步的,不太可能导致挂起。

但是,文件处理器线程还会扫描目录,这可能发生在Web蜘蛛线程将文件保存到目录中时。

问题: 如果在调用以下读取目录方法时将文件保存到此目录中,是否会导致挂起? (坦率地说,我不知道它怎么可能,但也许这就是为什么我有这个错误)。

如果是,那我该如何解决这个问题呢?

 private void listFiles(Path path)
{
    Log.getLogger().debug("started ......");
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path))
    {
        for (Path entry : stream)
        {
            if (Files.isDirectory(entry))
            {
                listFiles(entry);
            }
            else
            {
                files.add(entry);
            }
        }
    }
    catch (Exception e)
    {
        Log.getLogger().error(e.getMessage(), e);
    }
    Log.getLogger().debug("done");
}

1 个答案:

答案 0 :(得分:0)

为避免线程干扰彼此工作,应使用信号量(或其中最简单形式的互斥)。可以通过线程获取Sempaphores,以便在所谓的关键部分中运行代码。例如,本节中的代码可以访问ArrayList。如果多个线程访问该列表并在其中添加和删除元素,那么最终将获得ConcurrentModificationException。在其他情况下,您根本不会得到例外,但您的程序可能会出现意外情况(例如,请参阅the lost-update problem)。

如果您每次访问关键部分时都获得锁定,则其他线程将无法访问共享资源(本例中的列表或您的案例中的目录)。

为了实现此行为,您可以使用实现lock interface的类,创建一个对象并将其用作锁定,如下所示:

Object lock = new Object();

synchronized(lock) {
  // do critical work here
}

第三种也许是最无效(但最简单)的方法是为您的方法使用synchronized关键字。只能在一个类中调用一个在类中声明为synchronized的方法。