多线程环境中的mkdirs()函数

Eli*_*ane 6 java spring multithreading mkdirs

我正在创建文件和文件夹树.我正在改写多线程.我看到的唯一弱点是创建文件夹时.现在它一个接一个(深入).在我写下文件之前,我会检查路径是否存在.如果没有,我使用mkdirs来创建所有缺失的东西.

public void checkDir(String relativePath) {
        File file = new File(homePath + relativePath);
        if (!file.exists()) {
            if (file.mkdirs()) {
                log.info("Directory: " + homePath + relativePath + " is created!");
            } else {
                log.error("Failed to create directory: " + homePath + relativePath + " !");
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我有一个问题,当我使用两个线程时会发生什么.一个有A/B/C路径,另一个有A/B/D. 假设我只有一个文件夹但不存在B.所以他们都会检查路径是否存在并且想要创建它.因此其中一个可能会失败,因为另一个会更快.那么我该如何管理呢?

  1. 我正在考虑删除存在的条件并让它失败但是没有AlreadyExists异常我可以抓住..
  2. 首先创建目录树(但我认为会有更好的方法吗?)
  3. 将目录创建作为关键部分并使其顺序 - 不确定如何在春季执行此操作,但无论如何确定它是必要的并且不会太慢地减慢过程.

也许我过分思考,但从理论上讲,这种情况可能会发生.目前我使用常规Thread,但我想使用spring TaskExecutor.它自己处理关键部分,但这不是共享变量或任何东西,路径是不同的,所以我认为它不会识别它.

谢谢你的建议.

use*_*421 7

File.mkdirs()指定该方法以创建目录及其所有父目录(如果它们不存在).ERGO有呼吁是没有意义的exists().存在将得到反正检查.打电话exists()只是在浪费时间.mkdirs()本质上是一个原子操作:试图超越它是没有意义的.

请注意,返回值false不一定是失败.它可能只是表明路径中的所有目录都已存在.

基本上你的问题的前提是错误的.


小智 5

似乎没有一个答案可以解决mkdirs()是否是线程安全的问题,一个答案指出mkdirs()是原子的,但可能存在失败的情况。此函数本质上处理文件系统,因此它可能涉及对相应主机上的操作系统的系统调用,并且如果您不知道应用程序将要使用的目标系统,则可能无法确定那些系统调用是否实际上是线程安全的。被使用。

例如,即使mkdirs()在创建文件夹结构之前检查是否存在,在以下情况下会发生什么,

线程1调用mkdirs(),它固有地检查文件夹结构的存在并确定它不存在。那时,线程1被抢占。

线程2调用mkdirs(),它固有地检查文件夹结构的存在并确定它不存在,随后继续创建文件夹结构。

线程1再次启动,并继续尝试使用先前确定的文件夹结构创建文件夹结构。

那里发生了什么?我不知道,这种事件顺序很难测试,尤其是在知道create folder system调用在操作系统之间有所不同的情况下。为确保线程安全并避免引入可能难以跟踪和调试的错误,您最好的选择是在代码的此关键部分实现一定程度的互斥。

我想采取一种幼稚的方法并声明两个线程都可以访问的单个“全局”变量会很容易,例如布尔值b,然后在关键部分周围添加以下代码,

synchronized(b) {
     // Your critical section here
}
Run Code Online (Sandbox Code Playgroud)

这样可以保证,如果一个线程锁定了b,则只有一个线程将仅访问关键部分,而另一个则等待,从而确保两个线程都不会调用mkdir()。

但是,如果您想了解有关多线程以及如何在较低级别上实现互斥的更多信息,在这种情况下,我建议您查看信号量以及如何实现它们来解决此问题。