java - 为什么即使我不调用 get() 或 join(),这个 CompletableFuture 也能工作?
问题描述
我在学习时有一个问题CompletableFuture
。/方法是阻塞调用get()
。join()
如果我不打电话给他们怎么办?
此代码调用get()
:
// Case 1 - Use get()
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1_000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
}).get();
System.out.println("World!");
Thread.sleep(5_000L); // Don't finish the main thread
输出:
Hello
World!
此代码既不调用get()
也不调用join()
:
// Case 2 - Don't use get()
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1_000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
});
System.out.println("World!");
Thread.sleep(5_000L); // For don't finish main thread
输出:
World!
Hello
我不知道为什么案例 2 的可运行块正在工作。
解决方案
的整个想法CompletableFuture
是立即安排它们启动(尽管您无法可靠地判断它们将在哪个线程中执行),并且当您到达get
orjoin
时,结果可能已经准备好,即:CompletableFuture
可能已经完成。在内部,一旦管道中的某个阶段准备就绪,该特定阶段CompletableFuture
将被设置为完成。例如:
String result =
CompletableFuture.supplyAsync(() -> "ab")
.thenApply(String::toUpperCase)
.thenApply(x -> x.substring(1))
.join();
与以下内容相同:
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "ab");
CompletableFuture<String> cf2 = cf1.thenApply(String::toUpperCase);
CompletableFuture<String> cf3 = cf2.thenApply(x -> x.substring(1));
String result = cf3.join();
当您到达实际调用join
时,cf3
可能已经完成。get
并且join
只是阻塞直到所有阶段完成,它不会触发计算;立即安排计算。
一个小的补充是您可以在CompletableFuture
不等待管道执行完成的情况下完成 a :例如complete
, completeExceptionally
, obtrudeValue
(即使它已经完成,也可以设置它)obtrudeException
或cancel
. 这是一个有趣的例子:
public static void main(String[] args) {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
System.out.println("started work");
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
System.out.println("done work");
return "a";
});
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
cf.complete("b");
System.out.println(cf.join());
}
这将输出:
started work
b
所以即使工作开始了,最终的价值是b
,不是a
。
推荐阅读
- laravel - Laravel:htmlspecialchars() 期望参数 1 是字符串,带有锚标记文本?
- excel - 具有“整数”类型键和“整数动态数组”类型值的字典:类型不匹配错误
- blazor-webassembly - Blazor WebAssembly 身份验证
- sql - Node.js Sequelize:'where' 的多个条件
- javascript - 如何将 Javascript 文件正确包含到树枝模板 Symfony3.4 中
- javascript - 关于上下文管理器的任何提示,类似于 Javascript 中的 Python?
- javascript - 从数组中删除矩形括号并打印数据
- c - 广度优先搜索期间的浮点异常
- python - 如何在 python Open3d 中为网格添加纹理?
- sas - 如何使用 SAS 从表中获取高发生变量?