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!");
}
这样,问题就解决了.
分享到:
相关推荐
这里我们将深入探讨Java中与文件和目录相关的高级编程概念。 1. **Java IO 流**: Java的IO流库提供了处理输入和输出的强大工具,包括处理文件的读写。例如,`InputStream`和`OutputStream`是所有输入和输出流的...
在Java编程环境中,解压ZIP和RAR文件是常见的任务,特别是在处理数据传输、备份或集成系统时。本文将深入探讨如何使用Java实现这一功能,并提供详细的步骤和代码示例。 首先,我们来看如何使用Java来解压ZIP文件。...
Java Zip压缩和解压缩是Java开发中常见的文件处理任务,主要涉及到`java.util.zip`包中的类和方法。本文将详细讲解如何使用Java进行Zip文件的压缩与解压缩操作,并结合给定的标签"源码"和"工具"来探讨实际应用场景。...
本文将深入探讨如何使用Java API来完成这项工作,以及它在实际项目中的应用。 Java提供了一个名为`java.util.zip`的包,其中包含用于处理ZIP和GZIPTar等压缩格式的类。我们将主要关注ZIP格式,因为它是最常用的一种...
本实例将探讨如何利用Java的内置库`java.util.zip`来处理APK文件的压缩与解压缩操作。这个过程涉及到对文件流的处理,以及对ZIP文件格式的理解。 首先,我们要了解ZIP文件格式。ZIP是一种通用的文件压缩格式,它...
在Java编程语言中,开发一个文件管理系统是一项常见的任务,它涉及到对本地文件系统进行操作,如创建、读取、更新和删除文件。本系统适用于初学者,旨在提供基础的文件管理功能,帮助用户理解如何利用Java来处理文件...
在本主题中,我们将深入探讨`File`类结合字节流如何实现文件和目录的操作,特别是复制、删除、剪切(重命名)以及多线程环境下的文件下载。 首先,让我们来看看`File`类的一些核心方法: 1. `createNewFile()`:...
Java解压缩文件是Java开发中常见的一项操作,特别是在处理数据传输、软件安装包或资源包时。本篇文章将深入探讨如何使用Java进行文件的解压缩,以及相关工具和源码的使用。 首先,Java标准库提供了`java.util.zip`...
本文将深入探讨如何使用Java来实现这个功能,主要关注`FileUtil.java`文件中的代码实现。 首先,Java本身并不直接支持RAR格式的压缩和解压缩,因为它内置的`java.util.zip`库只提供了对ZIP和GZ格式的支持。然而,...
在本文中,我们将深入探讨Java如何进行文件的解压缩,并提供相关的代码示例。 首先,Java标准库提供了`java.util.zip`包,它包含了处理压缩文件所需的类。其中,`ZipInputStream`和`ZipOutputStream`分别用于读取和...
2. **文件操作方法**:`File`类中包含了多种文件操作方法,如`exists()`检查文件是否存在,`createNewFile()`创建新文件,`delete()`删除文件,`renameTo()`重命名文件,`mkdirs()`创建多级目录等。在`FileExecute....
在Java编程语言中,处理压缩和解压文件是一项常见的任务,可以用于数据备份、传输或者存储。Apache软件基金会提供了一套强大的工具集,其中包括用于处理压缩文件的组件,如Apache Commons Compress库。本篇文章将...
Java自定义工具类集合是一个程序员在开发过程中经常会创建和使用的资源。这些工具类通常包含了对常见编程任务的封装,提高了代码的复用性和可维护性。在这个特定的压缩包中,我们可以看到几个关键领域的工具类:File...
在Java编程中,高效地处理文件和目录的拷贝是一项常见的任务。为了简化这一过程,开发者经常选择将拷贝操作封装成工具类,以便在项目中便捷地复用。本篇将详细介绍如何创建一个用于拷贝文件及文件夹的工具类,并探讨...
首先,我们要了解Java标准库中的`java.util.zip`包,这个包提供了对ZIP文件格式的支持。主要涉及的类有`ZipEntry`和`ZipOutputStream`用于压缩,`ZipInputStream`用于解压缩。 1. **压缩(Zip)** - 创建一个`...
本文将深入探讨如何在Android环境中使用Java实现这一功能。 首先,我们要了解ZIP文件格式。ZIP是一种广泛使用的档案格式,它能将多个文件或目录打包成一个单一的文件,便于存储、传输和分发。ZIP文件内部包含了一个...
在实际开发中,你可能还需要考虑异常处理、多线程解压、内存效率优化等方面的问题。上述代码只是一个基础示例,实际应用中需要根据具体需求进行调整和完善。理解这些基本原理和操作后,你就能更灵活地处理各种ZIP...
- 异步I/O(Asynchronous File Channel)在Java NIO2中引入,允许在其他线程中执行文件操作,提高并发性能。 7. **安全性** - 文件操作应考虑权限和安全问题,避免出现未授权访问或数据泄露。使用`java.nio.file....
此外,`java.io.RandomAccessFile`类允许对文件进行随机访问,而`java.nio.file.Files`工具类则提供了一系列静态方法,简化了文件操作。 在多用户环境下,为了防止并发访问冲突,还需要引入锁机制。Java的`...
在编程中,Python的`os.mkdir()`或`os.makedirs()`,Java的`java.io.File.mkdirs()`,JavaScript的`fs.mkdirSync()`或异步的`fs.mkdir()`都可以完成相同任务,支持创建多级目录。 创建新文件的操作通常更为简单。在...