How to use mkdirs streaming in Java?

After you run into problems with mkdirs () and gouge through interwebs, I get the impression that with mkdirs () there are problems with thread safety.

Is there a way to ensure proper directory creation when it is possible that multiple threads might try to create similar file structures?

thanks

(In my case, I will use this on Android)

+7
source share
5 answers

Well, I know this has been inactive for a while, but I thought there might have been a simple solution. The article you pointed out in the comments on the question seems to indicate that the only problem is that directories are not created. The solution was to do this:

if (!f.mkdirs()) { f.mkdirs(); } 

However, this seems inefficient and may still have problems. So why not just do this:

 while (!f.mkdirs()) {} 

Simple but it works.

EDIT: After a little thought, this example may freeze and may cause thread blocking. So this might be a better idea:

 while (!f.mkdirs()) { Thread.yield(); } 

Of course, this would be recommended only if you are in a thread that could cause thread blocking, and so far this is not a priority situation. Just put it there.

0
source

I'm not sure if Android supports a parallel package, but here's my trick:

 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(); } } 

The method returns earlier if the directory already exists. If it does not exist, only one thread will try to create it.

+5
source

Do all your directory creation in a workflow that serializes everything. You can use Looper and Handler to make it easier to submit Runnables that invoke mkdirs for your workflow. When you are done creating directories, you can call Looper.quit () to terminate the stream after processing the last submitted Runnable . The documentation for Looper provides sample code that shows how nearly this is possible.

+3
source

One of the possible solutions could be MkDirService (see below), which guarantees only one instance and runs its own thread in it. Using BlockingQueue.

First service:

 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()); } } } } 

Test:

 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(); } } 
+2
source

Eaven, if this thread is a bit older, I wonder if there is anything wrong with the following solution:

 package service; import java.io.File; public class FileService { public static synchronized boolean mkdirs( File dir ) { return dir.mkdirs(); } } 
+1
source

All Articles