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

在遇到mkdirs()的问题并且在互联网上闲逛之后,我得到的印象是mkdirs()存在线程安全问题。 当多个线程可能尝试创建类似的文件结构时,有没有办法确保正确创建目录? 谢谢 (在我的情况下,我将在Android上使用此功能)     
已邀请:
好吧,我知道这已经暂停了一段时间,但我想也许有一个简单的解决方案。您在问题的评论中链接的文章似乎表明唯一的问题是没有创建目录。解决方案是这样做的:
if (!f.mkdirs()) {
    f.mkdirs();
}
但是,这似乎效率低下,仍然可能存在问题。那么,为什么不简单地这样做:
while (!f.mkdirs()) {}
简单,但它的工作原理。 编辑:经过一番思考后,该示例可能会滞后于遗忘并可能导致线程锁定。所以,这可能是一个更好的主意:
while (!f.mkdirs()) { Thread.yield(); }
当然,只有在你可能导致线程锁定的线程中,并且只要它不是高优先级的情况时,才会建议这样做。把它放在那里。     
我不确定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();
    }
}
如果目录已存在,则该方法会提前返回。如果它不存在,则只有一个线程会尝试创建它。     
在一个序列化所有内容的工作线程中创建所有目录。您可以使用
Looper
Handler
轻松发布调用mkdirs到工作线程的
Runnables
。当你完成制作目录时,你可以调用Looper.quit()来处理最后发布的
Runnable
后的线程。
Looper
的文档有示例代码,显示了这是多么微不足道的事情。     
一种可能的解决方案是MkDirService(如下图所示),它只保证一个实例并在其自己的线程中运行。利用BlockingQueue。 首先是服务:
package mkdir;

import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class MkDirService extends Thread {

    private static MkDirService service;
    private BlockingQueue<File> pendingDirs = new LinkedBlockingQueue<File>();
    private boolean run = true;

    private MkDirService() {
    }

    public synchronized static MkDirService getService() {
        if (service == null) {
            service = new MkDirService();
            new Thread(service).start();
        }
        return service;
    }

    public void makeDir(File dir) {
        pendingDirs.add(dir);
    }

    public void shutdown() {
        run = false;
    }

    @Override
    public void run() {
        while (run || !pendingDirs.isEmpty()) {
            File curDir = null;
            try {
                curDir = pendingDirs.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (curDir != null && !curDir.exists()) {
                curDir.mkdir();
                System.out.println("Made: " + curDir.getAbsolutePath());
            }
        }
    }
}
测试:
package mkdir;

import java.io.File;

public class MkDirServiceTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        MkDirService mdServ = MkDirService.getService();
        mdServ.makeDir(new File("test1"));
        mdServ.makeDir(new File("test1/test2"));
        mdServ.makeDir(new File("test1/test3"));
        mdServ.shutdown();

    }
}
    
Eaven如果这个线程有点老了我想知道以下解决方案是否存在一些错误:
package service;

import java.io.File;

public class FileService {

    public static synchronized boolean mkdirs( File dir ) {
        return dir.mkdirs();
    }
}
    

要回复问题请先登录注册