Java 在CompletableFuture中使用Supplier会产生与使用lambda不同的结果
我创建了一个读取文本文件并使用Java 在CompletableFuture中使用Supplier会产生与使用lambda不同的结果,java,lambda,java-8,completable-future,Java,Lambda,Java 8,Completable Future,我创建了一个读取文本文件并使用CompletableFuture包装调用的小示例 public class Async { public static void main(String[] args) throws Exception { CompletableFuture<String> result = ReadFileUsingLambda(Paths.get("path/to/file")); result.whenComplete((
CompletableFuture
包装调用的小示例
public class Async {
public static void main(String[] args) throws Exception {
CompletableFuture<String> result = ReadFileUsingLambda(Paths.get("path/to/file"));
result.whenComplete((ok, ex) -> {
if (ex == null) {
System.out.println(ok);
} else {
ex.printStackTrace();
}
});
}
public static CompletableFuture<String> ReadFileUsingSupplier(Path file) throws Exception {
return CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
return new String(Files.readAllBytes(file));
} catch (IOException e) {
e.printStackTrace();
return "test";
}
}
}, ForkJoinPool.commonPool());
}
public static CompletableFuture<String> ReadFileUsingLambda(Path file) throws Exception {
return CompletableFuture.supplyAsync(() -> {
try {
return new String(Files.readAllBytes(file));
} catch (IOException e) {
e.printStackTrace();
return "test";
}
} , ForkJoinPool.commonPool());
}
}
公共类异步{
公共静态void main(字符串[]args)引发异常{
CompletableFuture result=ReadFileUsingLambda(path.get(“path/to/file”);
结果。完成时((确定,ex)->{
如果(ex==null){
系统输出打印项次(ok);
}否则{
例如printStackTrace();
}
});
}
公共静态CompletableFuture ReadFileUsingSupplier(路径文件)引发异常{
返回CompletableFuture.SupplySync(新供应商(){
@凌驾
公共字符串get(){
试一试{
返回新字符串(Files.readAllBytes(file));
}捕获(IOE异常){
e、 printStackTrace();
返回“测试”;
}
}
},ForkJoinPool.commonPool());
}
公共静态CompletableFuture ReadFileUsingLambda(路径文件)引发异常{
返回CompletableFuture.SupplySync(()->{
试一试{
返回新字符串(Files.readAllBytes(file));
}捕获(IOE异常){
e、 printStackTrace();
返回“测试”;
}
},ForkJoinPool.commonPool());
}
}
此代码不返回任何内容。它执行并且“什么都没有发生”,没有错误或输出。如果我调用ReadFileUsingSupplier
而不是ReadFileUsingLambda
,那么我会在控制台中打印文件内容
对我来说,这没有意义,因为lambda是编写内联函数的简写,它不应该改变行为,但在本例中,它显然改变了行为。我认为这只是执行时间的问题-lambda可能需要更多的时间来执行,允许程序在读取文件之前退出 试试这个:
- 添加
作为线程睡眠(1000)
中try块中的第一条语句,您将看不到任何输出ReadFileUsingSupplier
- 添加
线程睡眠(1000)使用
时,代码>位于主文件末尾,您将看到预期的输出ReadFileUsingLambda
result.join();
如前所述,在任何情况下都需要result.join(),以避免主线程退出过快 当JVM升温时,使用lambdas vs匿名闭包似乎会受到惩罚,此后性能是相同的。我在上找到了这些信息,而这又是链接 顺便说一句,用Thread.sleep()来解决奇怪的计时问题从来都不是一个好主意。当你或其他人重新阅读时,找出原因并采取适当的措施会更加清晰
System.out.println(result.get(5, TimeUnit.SECONDS));
这使您也可以放弃.join()。谢谢。这确实起到了作用,但接下来我如何确保我的程序不会退出,直到我从CompletableFuture@SulAga您只需调用
result.get()
或result.join()
,那么join或get是一个阻塞调用?它是主线程上的阻塞还是CompletableFuture线程上的阻塞?这是个问题吗。blocking@SulAga它在调用它的线程上阻塞-如果您只是在main
的末尾添加result.join()
,它将阻塞主线程。