当我执行这段代码时,它会在流管道中打开许多文件:
public static void main(String[] args) throws IOException {
Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.map(file -> runtimizeException(() -> Files.lines(file, StandardCharsets.ISO_8859_1)))
.map(Stream::count)
.forEachOrdered(System.out::println);
}
我得到一个例外:
java.nio.file.FileSystemException: /long/file/name: Too many open files
问题是流。当完成对流的遍历时,count不关闭流。但我不明白为什么不应该,因为这是一个终端操作。对于其他终端操作,如reduce
和forEach
,也是如此<另一方面,代码>平面图关闭它所包含的流。
文档告诉我在必要时使用try with resources语句来关闭流。在我的例子中,我可以用以下内容替换计数行:
.map(s -> { long c = s.count(); s.close(); return c; } )
但这是嘈杂和丑陋的,在某些情况下,对于大型复杂的管道来说,可能会带来真正的不便。
我的问题如下:
RuntimeException是一种将选中的异常包装在RuntimeException中的方法。
您将需要在此流操作中调用lock()
,这将导致调用所有底层的关闭处理程序。
更好的是,将您的整个语句包装在一个try with resources块中,因为这样它将自动调用close处理程序。
这在您的情况下可能不太可能,这意味着您需要在某些操作中自行处理。您当前的方法可能根本不适合流。
看起来您确实需要在第二次map()
操作中执行此操作。
可以创建一个实用程序方法,可靠地关闭管道中间的流。
这确保了每个资源都用try with resource语句关闭,但避免了自定义实用程序方法的需要,并且比直接在lambda中编写try语句要详细得多。
使用此方法,问题中的管道如下所示:
Files.find(Paths.get("Java_8_API_docs/docs/api"), 100,
(path, attr) -> path.toString().endsWith(".html"))
.map(file -> applyAndClose(
() -> Files.lines(file, StandardCharsets.ISO_8859_1),
Stream::count))
.forEachOrdered(System.out::println);
实现如下所示:
/**
* Applies a function to a resource and closes it afterwards.
* @param sup Supplier of the resource that should be closed
* @param op operation that should be performed on the resource before it is closed
* @return The result of calling op.apply on the resource
*/
private static <A extends AutoCloseable, B> B applyAndClose(Callable<A> sup, Function<A, B> op) {
try (A res = sup.call()) {
return op.apply(res);
} catch (RuntimeException exc) {
throw exc;
} catch (Exception exc) {
throw new RuntimeException("Wrapped in applyAndClose", exc);
}
}
(由于需要关闭的资源在分配时通常也会抛出异常,非运行时异常被包装在运行时异常中,因此不需要单独的方法来完成此操作。)
这里有两个问题:处理已检查的异常,例如IOException,以及及时关闭资源。
没有一个预定义的功能接口声明任何选中的异常,这意味着它们必须在lambda中处理,或者包装在未选中的异常中并重新调用。看起来您的函数runtimizeException就是这样做的。您可能还必须为其声明自己的功能接口。正如你可能已经发现的那样,这是一种痛苦。
在关闭像文件这样的资源时,有人研究过在流结束时自动关闭流。这会很方便,但它不处理抛出异常时的关闭。在流中没有神奇的做正确的事情机制。
我们只剩下处理资源闭包的标准Java技术,即Java 7中引入的try-with-resources构造。TWR真的希望资源在调用堆栈中与打开时处于同一级别。适用“谁打开它,谁就必须关闭它”的原则。TWR还处理异常处理,这通常使在同一位置处理异常处理和资源关闭变得方便。
在这个例子中,流有点不寻常,因为它映射了一个Stream
构建该管道的另一种方法如下。
Files.lines
调用是打开文件的调用,所以这必须是TWR语句中的资源。这个文件的处理是抛出(一些)IOExceptions
的地方,所以我们可以在同一个TWR语句中进行异常包装。这建议有一个简单的函数,将路径映射到行数,同时处理资源关闭和异常包装:
long lineCount(Path path) {
try (Stream<String> s = Files.lines(path, StandardCharsets.ISO_8859_1)) {
return s.count();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
一旦有了这个helper函数,主管道如下所示:
Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.mapToLong(this::lineCount)
.forEachOrdered(System.out::println);
获取频道报表 获取频道资金流水 获取频道打赏流水 获取频道发红包/抢红包记录 获取频道付费流水 获取观众观看流水_V2 获取观众观看流水_V1 获取频道报名问卷数据 获取频道问卷列表数据 获取频道观众列表V2 获取频道观众列表
问题内容: 我正在玩Golang,我创建了这个小应用程序,使用goroutines进行了多个并发的api调用。 当应用程序运行时,调用完成后,该应用程序将卡住,这是有道理的,因为由于通道未关闭,无法退出 范围c 循环。 我不确定在哪种情况下可以更好地关闭该通道。 问题答案: 当没有更多值要发送时,您将关闭通道,因此在这种情况下,所有goroutine已完成。 (请注意,from 仅将反映连接和协议
想知道是否有某种“钩子”来放置apache beam管道关闭时将执行的一段代码(无论出于何种原因-崩溃、取消) 每次数据流停止时,我都需要删除pubsub主题的订阅。
关闭通道的意思是该通道将不再允许写入数据。这个方法可以让通道数据的接受端知道数据已经全部发送完成了。 package main import "fmt" // 在这个例子中,我们使用通道jobs在main函数所在的协程和一个数据 // 接收端所在的协程通信。当我们数据发送完成后,我们关闭jobs通道 func main() { jobs := make(chan int, 5) d
关闭RSS频道 停止内容之播放后,于显示频道一览时按下按钮。 提示 关闭RSS频道之行为并无法同时切断网络联机。若想切断联机,请将无线LAN按钮调整为OFF(关)。