`
panxq0809
  • 浏览: 294611 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

对java中File.mkdirs方法线程安全问题的一点探讨

    博客分类:
  • java
阅读更多

mkdirs是java中用来一次创建多级目录的方法,在java.io.File类中。

我在编程中遇到这样一段代码:
    if (!dest.exists()) {
        dest.mkdirs();
    }
    if (!dest.isDirectory()) {
      throw new IOException(dest.getName() + " must be a directory!");
    }

该段代码所在的方法会被多个线程调用。在某些次的运行中,dest.mkdirs方法创建目录就会失败,从而造成下面的if语句里的抛异常代码被执行。

JDK 1.5 update 21中的java.io.File.mkdirs代码如下:
    public boolean mkdirs() {
         if (exists()) {
             return false;
         }
         if (mkdir()) {
            return true;
        }
        File canonFile = null;
        try {
            canonFile = getCanonicalFile();
        } catch (IOException e) {
            return false;
        }
         String parent = canonFile.getParent();
        return (parent != null) &&
               (new File(parent, fs.prefixLength(parent)).mkdirs() &&
                                    canonFile.mkdir());
    }

考察该mkdirs源码,发现在这种可能的情形中,会出问题:两个线程都调用最前面那段代码,第一个线程中要创建的目录为“dirParent/dirA”,第二个线程要创建的目录为“dirParent/dirB”(执行以前dirParent目录不存在)。这两个线程都进入mkdirs方法,两个线程都没能直接创建目录并执行到“return”语句那一行,接下来,第一个线程执行完毕并成功创建了“dirParent/dirA”目录,这时第二个线程向前推进,对mkdirs方法的递归调用由于“dirParent”目录已存在而返回false,由“&&”运算符的短路机制,“canonFile.mkdir()”语句将不会被执行,也就是说“dirB”目录并没有被创建出来,且此时mkdirs也将返回false。于是,在第二个线程中,后面的抛出异常的语句就被执行。

这样看来,mkdirs方法并不是线程安全的。针对这段程序的实际情况,我将最上面的代码改成下面这样(FileUtils是该段代码所在的类,且该段代码所在的方法为静态方法):
    if (!dest.exists()) {
        synchronized (FileUtils.class) {
            dest.mkdirs();
        }
    }
    if (!dest.isDirectory()) {
      throw new IOException(dest.getName() + " must be a directory!");
    }
这样,问题就解决了.

分享到:
评论
1 楼 adam6948 2012-08-08  
碉堡了,正遇到这这问题头疼呢。茅塞顿开...我的问题更为隐晦,手动删掉上次执行程序创建的部分目录。用myeclipse 直接执行是没有错误的,并重新创建。然而用debug的时候就不在重新创建造成错误.

相关推荐

    new file()创建不出文件 解决 Android无法创建File问题

    Android 无法创建File文件 ,在上传图片的时候报错,提示file文件夹未空或在手机清空缓存删除文件夹后 文件夹无法创建 使用file.mkdirs()方法 返回一直是false 提供的功法可以直接解决该问题

    对python中的 os.mkdir和os.mkdirs详解

    今天小编就为大家分享一篇对python中的 os.mkdir和os.mkdirs详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    org.apache.tools.zip解决解压乱码问题

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util....

    java算法,实现压缩及解压缩

     import java.io.File;  import java.io.FileInputStream;  import java.io.FileOutputStream;  import java.util.zip.ZipEntry;  import java.util.zip.ZipOutputStream;  public class Zip {  static...

    Java生成二维码

    Java生成二维码 Hashtable, Object> hints = new Hashtable, Object>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); BitMatrix byteMatrix; try { byteMatrix = new ...

    java压缩文件源码--ZipUtils

    new File(rootDir+file.separator+path).mkdirs(); log("entry:"+entryName.substring(0, index)); } else{ new File(rootDir).mkdirs(); log("entry:"+entryName); } return entryName; ...

    3Java SE(下).doc

    1.java.io.File: 该类用来表示一个文件或目录,使用它可以: 1:访问文件或目录的属性(名字,大小,最后修改时间等) 2:操作文件或目录(创建,删除) eg: File file = new File("."+File.separator+"test.txt...

    java上传文件实例

    <%@page import="java.io.File,java.util.Date;"%> String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> ...

    andriod开发 读写文件

    import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; public class CreateFiles { String filenameTemp = Info.audioPath + "/...

    hadoop1.0 Failed to set permissions of path 解决方案

    at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:344) at org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:189) at org.apache.hadoop.mapred.TaskTracker....

    图片文件上次,获取图片文件实际类型

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java....

    Android代码-安卓视频上传与下载

    android-vedio-upload-and-download 安卓视频上传与下载 核心代码: if (localUrl == null) { localUrl = Environment.getExternalStorageDirectory() .getAbsolutePath() ....mkdirs(); try {

    hadoop-2.6.0-hadoop.dll-winutils.exe

     at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:444)  at org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:293)  at org.apache.hadoop.mapreduce....

    node-file-utils:异步节点文件系统实用程序的集合

    file.mkdirs(路径,模式,回调) 将所有目录放在路径中。 (类似于mkdir -P)例如,在空目录中,给定类似“ test / this / path”的路径,mkdirs将使目录成为“ test”,“ this”和“ path”。 file.mkdirsSync...

    java文件复制

    文字复制的java代码 public class file { public void copyFolder(String oldPath, String newPath) { try { (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹 File a=new File(oldPath); ...

    pdfbox-2.0.7.jar

    pdf分割成图片,java代码读取pdf并且将pdf以页为单位分割成图片 File file = new File(pdfPath); PDDocument doc; try { doc = PDDocument.load(file); PDFRenderer renderer = new PDFRenderer(doc); ...

    Android代码-FileDownloaderFinal

    在App Application中添加一下配置 private void initDownloaderManager() { //下载文件所保存的目录 File storeFile = StorageUtils.getCacheDirectory(this, false, "FileDownloader"); if (!storeFile.exists()...

    Android相机调用

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.Locale; import android.annotation....

    Java程序设计(第二版)大纲、考试模拟试题及答案

    file1.mkdirs(); File file2=new File(file1,"1.txt"); file2.createNewFile(); String s="I like java."; byte[] b=s.getBytes(); FileOutputStream out=new FileOutputStream(file2); out.write(b); ...

Global site tag (gtag.js) - Google Analytics