To create a new, unique filename, I use the following code:
File file = new File(name);
synchronized (sync) {
int cnt = 0;
while (file.exists()) {
file = new File(name + " (" + (cnt++) + ")");
}
file.createNewFile();
}
Next, I use the file and delete it.
When I do this in a multithreaded situation, I sometimes get exceptions on the file.createNewFile()
:
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1012)
The following code reproduces the problem (most of the times):
final int runs = 1000;
final int threads = 5;
final String name = "c:\\temp\\files\\file";
final byte[] bytes = getSomeBytes();
final Object sync = new Object();
ExecutorService exec = Executors.newFixedThreadPool(threads);
for (int thread = 0; thread < threads; thread++) {
final String id = "Runnable " + thread;
exec.execute(new Runnable() {
public void run() {
for (int i = 0; i < runs; i++) {
try {
File file = new File(name);
synchronized (sync) {
int cnt = 0;
while (file.exists()) {
file = new File(name + " (" + (cnt++) + ")");
}
file.createNewFile();
}
Files.write(file.toPath(), bytes);
file.delete();
} catch (Exception ex) {
System.err.println(id + ": exception after " + i
+ " runs: " + ex.getMessage());
ex.printStackTrace();
return;
}
}
System.out.println(id + " finished fine");
}
});
}
exec.shutdown();
while (!exec.awaitTermination(1, TimeUnit.SECONDS));
The method getSomeBytes()
just generates an amount of bytes, the actual content is not important:
byte[] getSomeBytes() throws UnsupportedEncodingException,
IOException {
byte[] alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ1234567890\r\n"
.getBytes("UTF-8");
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
for (int i = 0; i < 100000; i++) {
baos.write(alphabet);
}
baos.flush();
return baos.toByteArray();
}
}
When I execute this code, it sometimes goes well but most of the times, it generates some exceptions like the output below for instance:
Runnable 1: exception after 235 runs: Access is denied
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1012)
at test.CreateFilesTest$1.run(CreateFilesTest.java:36)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Runnable 4: exception after 316 runs: Access is denied
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1012)
at test.CreateFilesTest$1.run(CreateFilesTest.java:36)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Runnable 2: exception after 327 runs: Access is denied
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1012)
at test.CreateFilesTest$1.run(CreateFilesTest.java:36)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Runnable 3 finished fine
Runnable 0 finished fine
Any ideas? I have tested on a Windows 8 machine with java 1.7.0_45 and 1.8.0_31, both same results.
Not sure whether the problem is the same as in this question, but it can be. Using multiple threads in the same process seems to be part of the problem to my opinion but I can't be sure about that, it's faster reproduced however.