I create a tree of files and folders. I am rewriting multithreading. The only weak point that I see is the creation of folders. Now he goes one after another (in depth). Before writing a file, I check if the path exists. If not, I use mkdirs to create everything that is missing.
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 + " !"); } } }
My question is what happens when I use two threads. One has an A / B / C path, and the other A / B / D. Say I have only folder A, but not B. Thus, both of them will check that the path does not exist and needs to be created. Therefore, one of them is likely to fail, because the other will be faster. So how can I do this?
, , . Thread, spring TaskExecutor. , - , , , .
.
File.mkdirs() , . Ergo exists(). . exists() - . mkdirs() - , , : .
File.mkdirs()
exists().
exists()
mkdirs()
, false . , .
false
, , mkdirs() , , mkdirs() , , . , , , , , , , , , , .
, mkdirs() , ,
Thread 1 mkdirs(), , . Thread 1 .
Thread 2 mkdirs(), , , .
1 , , .
? , , , create folder . , , .
, "" , , b, ,
synchronized(b) { // Your critical section here }
, b, , , , mkdir() .
, , , .
EJP, false , , . , , :
public final class DirectoryHelper { private DirectoryHelper(){} public static boolean createDirectories(File path) { if (path.mkdirs()) return true; //definitely has new dir // if false, just look afterwards for the existence of the directory // also opportunity to throw own exceptions if you prefer return path.exists() && path.isDirectory(); } }
I wrote a new method here that returns false only if the directory does not exist. I don’t care that this is already done or already exists. Due to the new order, I don't need a block synchronized.
synchronized
Then your code looks like this:
public void checkDir(String relativePath) { File file = new File(new File(homePath), relativePath); if (!file.exists()) { // just to prevent logging of existing dirs if (DirectoryHelper.createDirectories(file)) { log.info("Directory: " + file + " is created!"); } else { log.error("Failed to create directory: " + file + " !"); } } };