我有一个难以复制的错误,其中一个线程挂起。
由于文件处理器移动文件(按逻辑必要性)只能在文件已经在目录中时发生,因此文件处理器文件读取过程是异步的,不太可能导致挂起。
但是,文件处理器线程还会扫描目录,这可能发生在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");
}
答案 0 :(得分:0)
为避免线程干扰彼此工作,应使用信号量(或其中最简单形式的互斥)。可以通过线程获取Sempaphores,以便在所谓的关键部分中运行代码。例如,本节中的代码可以访问ArrayList
。如果多个线程访问该列表并在其中添加和删除元素,那么最终将获得ConcurrentModificationException
。在其他情况下,您根本不会得到例外,但您的程序可能会出现意外情况(例如,请参阅the lost-update problem)。
如果您每次访问关键部分时都获得锁定,则其他线程将无法访问共享资源(本例中的列表或您的案例中的目录)。
为了实现此行为,您可以使用实现lock interface的类,创建一个对象并将其用作锁定,如下所示:
Object lock = new Object();
synchronized(lock) {
// do critical work here
}
第三种也许是最无效(但最简单)的方法是为您的方法使用synchronized
关键字。只能在一个类中调用一个在类中声明为synchronized的方法。