![](/img/trans.png)
[英]How to pass lists through the constructor in a thread-safe manner in Java?
[英]How to use mkdirs in a thread safe manner in Java?
在遇到mkdirs()的问题并且在互联网上闲逛之后,我得到的印象是mkdirs()存在线程安全问题。
当多个线程可能尝试创建类似的文件结构时,有没有办法确保正确创建目录?
谢谢
(在我的情况下,我将在Android上使用此功能)
我不确定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();
}
}
如果目录已存在,则该方法会提前返回。 如果它不存在,则只有一个线程会尝试创建它。
一种可能的解决方案是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();
}
}
好吧,我知道这已经暂停了一段时间,但我想也许有一个简单的解决方案。 您在问题的评论中链接的文章似乎表明唯一的问题是没有创建目录。 解决方案是这样做的:
if (!f.mkdirs()) {
f.mkdirs();
}
但是,这似乎效率低下,仍然可能存在问题。 那么,为什么不简单地这样做:
while (!f.mkdirs()) {}
简单,但它的工作原理。
编辑:经过一番思考后,该示例可能会滞后于遗忘并可能导致线程锁定。 所以,这可能是一个更好的主意:
while (!f.mkdirs()) { Thread.yield(); }
当然,只有在你可能导致线程锁定的线程中,并且只要它不是高优先级的情况时,才会建议这样做。 把它放在那里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.