使用async / await可以以命令式样式编写异步函数。这可以极大地促进异步编程。自从C#首次引入以来,它已被JavaScript,Python和Kotlin等许多语言所采用。
EA Async是一个向Java添加类似于异步/等待功能的库。该库消除了使用CompletableFutures的复杂性。
但是为什么既未将async / await添加到Java SE中,又未计划在将来添加它?
答案 0 :(得分:11)
简短的答案是Java的设计者试图消除对异步方法的需求,而不是促进它们的使用。
根据罗恩·普勒斯勒(Ron Pressler)的talk使用CompletableFuture进行异步编程会导致三个主要问题。
虽然异步/等待解决了第一个问题,但它只能部分解决第二个问题,而根本解决不了第三个问题(例如,C#中所有执行 的方法都必须标记为< em> async )。
但是为什么根本需要异步编程?只是为了防止线程阻塞,因为线程很昂贵。因此,不是在Java中引入异步/等待,而是在Loom项目中,Java设计人员正在研究光纤(也称为轻量级线程),其目的是显着降低线程的成本,从而消除对异步编程的需求。这将使以上所有三个问题也过时。
答案 1 :(得分:1)
迟到总比不到好!!! Java 在尝试提出可以并行执行的更轻量级的执行单元方面晚了 10 多年。附带说明一下,Project Loom 还旨在在 Java 中公开“分隔继续”,我认为这只不过是 C# 的老式“yield”关键字(又晚了将近 20 年!!)
Java 确实认识到需要解决由 asyn await(或实际上 C# 中的任务,这是一个伟大的想法。Async Await 更像是一种语法糖。非常显着的改进,但仍然不是解决操作系统映射线程的实际问题比预期的要重)。
在此处查看项目织机的提案:https://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html 并导航到最后一节“其他方法”。你会明白为什么 Java 不想引入 async/await。
话虽如此,我并不完全同意所提供的推理。无论是在这个提案中,还是在 Stephan 的回答中。
首先让我们诊断斯蒂芬的答案
Stephan 是对的,他说需要异步编程来防止 (OS) 线程阻塞,因为 (OS) 线程很昂贵。这正是需要虚拟线程(或 C# 任务)的全部原因。您应该能够“阻止”这些任务而不会失眠。当然为了不失去睡眠,调用例程本身应该是一个任务,或者阻塞应该在非阻塞 IO 上,框架足够聪明,在这种情况下不会阻塞调用线程(延续的力量)。
C# 支持这一点,并且提议的 Java 特性旨在支持这一点。 根据提议的 Java api,在虚拟线程上阻塞将需要在 Java 中调用 vThread.join() 方法。 它比调用 await workDoneByVThread() 有什么好处?
现在让我们来看看项目织机提案的推理
<块引用>延续和纤程在 async/await 中占主导地位,因为 async/await 很容易用延续来实现(事实上,它可以用一种弱形式的分隔延续来实现,称为无堆栈延续,它不会捕获整个调用-stack 但只是单个子程序的本地上下文),反之亦然
我并不简单地理解这句话。如果有人这样做,请在评论中告诉我。
对我来说,async/await 是使用 continuation 实现的,就堆栈跟踪而言,由于光纤/虚拟线程/任务在虚拟机内,因此必须可以管理该方面。事实上,.net 工具确实可以做到这一点。
<块引用>虽然 async/await 使代码更简单,并赋予它正常、顺序代码的外观,但与异步代码一样,它仍然需要对现有代码进行重大更改、库中的显式支持,并且不能与同步代码很好地互操作
我已经介绍过了。不对现有代码进行重大更改并且库中没有明确支持实际上意味着不能有效地使用此功能。直到并且除非 Java 旨在将所有线程透明地转换为虚拟线程(它不能也不能),否则此声明对我来说没有意义。
作为一个核心思想,我发现 Java 虚拟线程和 C# 任务之间没有真正的区别。就这一点而言,project Loom 也针对默认情况下窃取工作的调度程序,与 .Net 默认使用的调度程序相同(https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler?view=net-5.0,滚动到最后的备注部分)。 似乎只有争论应该采用什么语法来消费这些。
采用C#
Java 的目标是:
恕我直言,Java 的选择比 C# 的差。拥有单独的接口和类实际上可以很清楚地表明行为有很大不同。当程序员没有意识到她现在正在处理不同的事情时,或者当库实现更改以利用新构造但最终阻塞调用(非虚拟)线程时,保留相同的旧接口可能会导致细微的错误。< /p>
也没有特殊的语言语法意味着阅读异步代码仍然难以理解和推理(我不知道为什么 Java 认为程序员喜欢 Java 的 Thread 语法,他们会很高兴知道而不是编写同步寻找他们将使用可爱的 Thread 类的代码)
哎呀,即使是 Javascript 现在也有异步等待(以及它所有的“单线程”)。