如何在Java中以线程安全的方式使用mkdirs?

cot*_*aws 9 java io android thread-safety mkdir

在遇到mkdirs()的问题并且在互联网上闲逛之后,我得到的印象是mkdirs()存在线程安全问题.

当多个线程可能尝试创建类似的文件结构时,有没有办法确保正确创建目录?

谢谢

(在我的情况下,我将在Android上使用此功能)

Aar*_*lla 5

我不确定Android是否支持并发包,但这是我的看法:

private static Lock fsLock = new ReentrantLock();

private void mkdir( File dir ) throws FileNotFoundException {

    if( dir.exists() ) {
        return;
    }

    fsLock.lock();
    try {
        if( !dir.exists() ) {
            log.info( "Creating directory {}", dir.getAbsolutePath() );
            if( !dir.mkdirs() ) {
                throw new FileNotFoundException( "Can't create directory " + dir.getAbsolutePath() );
            }
        }
    } finally {
        fsLock.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果目录已存在,则该方法会提前返回.如果它不存在,则只有一个线程会尝试创建它.


Ale*_*ing 1

好吧,我知道这已经有一段时间不活跃了,但我想也许有一个简单的解决方案。您在该问题的评论中链接的文章似乎表明唯一的问题是创建目录。解决方案是这样做:

if (!f.mkdirs()) {
    f.mkdirs();
}
Run Code Online (Sandbox Code Playgroud)

然而,这似乎效率低下,并且仍然可能存在问题。那么,为什么不简单地这样做:

while (!f.mkdirs()) {}
Run Code Online (Sandbox Code Playgroud)

简单,但有效。

编辑:经过一番思考,该示例可能会滞后并可能导致线程锁定。所以,这可能是一个更好的主意:

while (!f.mkdirs()) { Thread.yield(); }
Run Code Online (Sandbox Code Playgroud)

当然,只有当您所在的线程可能导致线程锁定并且不是高优先级情况时才建议这样做。只是把这个放在那里。

  • ...并且真的,真的希望这永远不会在 mkdirs() 由于真正原因(例如权限问题或格式错误的目录名)失败的情况下运行。 (3认同)