- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个包含 JSON 文件的目录,需要迭代该目录才能获取文档 dName
的名称。多个 JSON 文件可以具有相同的 dName
。然后,需要从名为 output/dName/match
的文件夹创建到该 JSON 文件的符号链接(symbolic link)。线程首先检查 dName 文件夹是否存在,如果不存在,则首先创建它们。我有以下创建符号链接(symbolic link)的代码。
protected static void copyFile(String docName, Path tFilePath) throws IOException {
final String docFolderName = "output" + docName.substring(0, docName.lastIndexOf("."));
final String opDir = docFolderName + "match";
path = Paths.get(opDir);
if (Files.notExists(path)) {
Files.createDirectories(path);
outputAnnotationDirs.add(path.toString());
}
try {
Files.createSymbolicLink(Paths.get(opDir).resolve(tFilePath.getFileName()), tFilePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected static void Mapper(String Dir,int numThreads) throws Exception {
final ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
final ConcurrentLinkedQueue<Future<?>> futures = new ConcurrentLinkedQueue<Future<?>>();
final JsonParser parser = new JsonParser();
try {
Files.walkFileTree(Paths.get(Dir), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path tFile, BasicFileAttributes attrs) throws IOException {
futures.add((Future<String>) executorService.submit(new Runnable() {
public void run() {
JsonObject jsonObject = null;
FileReader reader = null;
try {
reader = new FileReader(tFile.toFile());
jsonObject = (JsonObject) parser.parse(reader);
JsonArray instancesArray = (JsonArray) jsonObject.get("instances");
String dName = instancesArray.get(0).getAsJsonObject().get("dname").toString();
copyFile(dName, tFile);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
logger.error(e);
}
}
}
}));
return FileVisitResult.CONTINUE;
}
});
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
Future<?> future;
while ((future = futures.poll()) != null) {
try {
future.get();
} catch (Exception e) {
for (Future<?> f : futures)
f.cancel(true);
if (executorService != null)
executorService.shutdown();
throw new Exception(e);
}
}
if (executorService != null)
executorService.shutdown();
}
}
但是,在创建符号链接(symbolic link)的行处不断发生异常。
Exception in thread "main" java.lang.Exception: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.nio.file.NoSuchFileException:`
例如:output/document1/match/ok.json
处出现异常
如果我是对的,只有在执行该行之后才会创建符号链接(symbolic link)。那么为什么会出现这个错误呢?线程创建的单个符号链接(symbolic link)为什么会导致concurrent.ExecutionException?
最佳答案
Then why does the error occur?
发生错误的原因是您的“父目录创建”在创建符号链接(symbolic link)之前未创建所有父目录。例如:如果您有 "dname": "a/b/c/somedname1.txt"
的 json 条目 - 文件夹 a/b/c
似乎未创建。这就是抛出 NoSuchFileException
的原因。现在,您已经有了创建目录的逻辑,但为什么不起作用呢?如果您在单线程中运行它,那就可以很好地工作。为什么不在多线程中呢?
因为,path
变量在所有线程之间共享,并且同时被许多线程修改。
path = Paths.get(opDir);
if (Files.notExists(path)) {
Files.createDirectories(path);
outputAnnotationDirs.add(path.toString());
}
例如,当在多个线程中运行时,一个线程具有 dname:a/b/c/dname1.txt
,第二个线程具有 dname:e/f/g/dname2.txt
。第一个线程最终可能会创建 e/f/g 而不是 a/b/c 目录。经典的并发问题。将该 path
设为局部变量将立即解决您的问题。或者在单线程中运行您的进程。
java.io.FileNotFoundException
。java.nio.file.FileAlreadyExistsException
。 java.nio.file.NoSuchFileException
当您无法对文件进行操作(例如 DELETE)时会发生。或者当您尝试在父文件夹不存在时创建文件/符号链接(symbolic link)时。 And individual Symbolic Link creation by a thread why does it cause concurrent.ExecutionException?
当您对 future
执行 get
时,NoSuchFileException
会被您的 RunTimeException
包装,而 RunTimeException
会被 ExecutionException
包装。因为, RunTimeException 发生在不同的线程上,而您的以下调用发生在主线程上。因此,Executor 包装了 Exception 并在以下从主线程调用的调用中触发。
future.get();
谢谢。
关于java - 创建符号链接(symbolic link)时的并发执行异常和 nio.file.NoSuchFileException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33697054/
我花了相当多的时间尝试优化文件哈希算法,以尽可能地提高性能。 查看我之前的 SO 主题: Get File Hash Performance/Optimization FileChannel Byte
我不太明白它们之间有什么不同,所以我对这两个包有一些疑问。 在 Google 上浏览了一下之后,似乎 Oracle 决定使用更新和增强的 NIO.2 包来更新 NIO 包,作为 JDK7 版本的一部分
在 Java 1.4 之前,通过在不同的输入流/输出流之间移动字节来处理文件是常见的做法。 自 Java 1.4 起,其中 NIO已添加,建议使用 Channels 执行相同操作。 与 NIO2在 J
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我需要重写一些应该在 Java 6 VM 上运行的 Java 7 文件 IO 代码。 该实现使用了方便的 Java 7 功能,例如自动关闭、Paths 和 Files。 更具体地说,我需要处理像 /t
当我查看java中Scanner的源代码时,我发现一些让我困惑的事情 import java.nio.file.Path; import java.nio.*; 它们之间有什么区别,为什么它们不直接导
我的 Java 代码中几乎所有文件 I/O 操作都使用 java.nio.*。然而,在今天调试一段代码时,我注意到调试器 (Intellij IDEA 14) 显示了以下关于 java.nio.fil
奇怪的是,我无法在 Google 中找到 NIO.2 异步 IO 性能与通过 java.nio.channels.Selector 使用 NIO 的多路复用 IO 的明确答案。 所以,我的问题是:NI
我是初级 Java 程序员。 今天,我练习了如何在 java 中复制文件并尝试按照本教程进行操作 http://www.journaldev.com/861/4-ways-to-copy-file-i
我有一个指向绝对路径的 java.nio.Path: /home/user/project/resources/configuration.xml 我有第二个 java.nio.Path 指向项目的根
我开始使用java.nio.*,现在我想知道:为什么java.nio.Paths.get(..)不使用java.nio.Path 对象作为输入? 现在我总是做这样的事情: final Path bas
我是新手,正在学习 Java。我尝试在 Netbeans 7 中运行以下应用程序。 import java.io.*; import java.nio.file.*; import java.nio.
我的 Java 程序(见下文)有时会在 java.nio.File.move() 方法执行中因 java.nio.file.AccessDeniedException 崩溃。 我不明白为什么会抛出这个
所以我在这里阅读我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式),特别是关于 Proactor/Reactor 异步 IO 模式的部分。我可以看到通过使用可选 channel
我有一个方法如下,它已经正常运行了很长时间: private String loadFromFile(){ RandomAccessFile inFile = null; FileCh
我在 IntellijIDEA Community Edition 2017.3 版本中收到以下错误。该项目使用java版本“1.8.0-ea”。请给我一些解决问题的想法 Error:Internal
一 点睛 在 scatter-and-gather 场景下,可以将数据写入多个 Buffer 中。在 NIO 中,也能够同时操作多个缓冲区。在很多 Channel 实现类中,都提供了多个重载的 rea
I/O简介 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
我是一名优秀的程序员,十分优秀!