EA Async 在 JVM 中实现 Async-Await 方法。它允许程序员以顺序方式编写异步代码。
它很大程度上受到 .NET CLR 上的 Async-Await 的启发,请参阅使用 Async 和 Await 进行异步编程以获取更多信息。
EA Async 应用于编写大量使用 CompletableFutures 或 CompletionStage 的非阻塞异步代码。它通过在代码等待其他进程时释放工作线程来提高可伸缩性;并通过使异步代码更简单、更具可读性来提高生产力。
该项目由 Electronic Arts 开发,并根据 BSD 3-Clause License 获得许可。
import static com . ea . async . Async . await ;
import static java . util . concurrent . CompletableFuture . completedFuture ;
public class Store
{
public CompletableFuture < Boolean > buyItem ( String itemTypeId , int cost )
{
if (! await ( bank . decrement ( cost ))) {
return completedFuture ( false );
}
await ( inventory . giveItem ( itemTypeId ));
return completedFuture ( true );
}
}
在此示例中, Bank.decrement
返回CompletableFuture<Boolean>
, Inventory.giveItem
返回CompletableFuture<String>
EA Async 重写了对Async.await
调用,使您的方法成为非阻塞的。
这些方法看起来是阻塞的,但实际上会转换为异步方法,这些方法使用 CompletableFutures 在中间结果到达时继续执行。
这是第一个示例在没有 EA Async 的情况下的样子。它的可读性有点差。
import static java . util . concurrent . CompletableFuture . completedFuture ;
public class Store
{
public CompletableFuture < Boolean > buyItem ( String itemTypeId , int cost )
{
return bank . decrement ( cost )
. thenCompose ( result -> {
if (! result ) {
return completedFuture ( false );
}
return inventory . giveItem ( itemTypeId ). thenApply ( res -> true );
});
}
}
这是一个小例子......具有更多 CompletableFutures 的方法可能看起来非常复杂。
EA Async 抽象了 CompletableFutures 的复杂性。
那么你喜欢 CompletableFutures 吗?尝试将此方法转换为仅使用 CompletableFutures 而不会阻塞(因此不会加入):
import static com . ea . async . Async . await ;
import static java . util . concurrent . CompletableFuture . completedFuture ;
public class Store
{
public CompletableFuture < Boolean > buyItem ( String itemTypeId , int cost )
{
if (! await ( bank . decrement ( cost ))) {
return completedFuture ( false );
}
try {
await ( inventory . giveItem ( itemTypeId ));
return completedFuture ( true );
} catch ( Exception ex ) {
await ( bank . refund ( cost ));
throw new AppException ( ex );
}
}
}
知道了?将其发送给我们。大概长得丑吧……
EA Async 目前支持 JDK 8-10。
它适用于 Java 和 Scala,并且应该适用于大多数 JVM 语言。使用 EA Async 的唯一要求是只能在返回CompletableFuture
、 CompletionStage
或CompletableFuture
子类的方法内部使用。
< dependency >
< groupId >com.ea.async</ groupId >
< artifactId >ea-async</ artifactId >
< version >1.2.3</ version >
</ dependency >
'com.ea.async:ea-async:1.2.3'
使用额外的 JVM 参数启动您的应用程序: -javaagent:ea-async-1.2.3.jar
java -javaagent:ea-async-1.2.3.jar -cp your_claspath YourMainClass args...
建议将此作为默认选项添加到使用 ea-async 的 IntelliJ 项目中的启动器。
在您的主课上或尽早致电至少一次:
Async.init();
如果您的 JVM 启用了该功能,这将启动运行时检测代理。如果您忘记调用此函数,则第一次调用await
将初始化系统(并打印警告)。
这是一个用于测试和开发的解决方案,它具有最少的配置。它可能会干扰 JVM 调试。此替代方案作为后备方案存在。
ea-async-1.2.3.jar 是一个可运行的 jar,可以预先检测您的文件。
用法:
java -cp YOUR_PROJECT_CLASSPATH -jar ea-async-1.2.3.jar classDirectory
例子:
java -cp guava.jar ; commons-lang.jar -jar ea-async-1.2.3.jar target/classes
之后,目标/类中的所有文件都将被检测。这些类中不会留下对Async.await
和Async.init
的引用。
使用 ea-async-maven-plugin。它将在编译时检测您的类并删除对Async.await
和Async.init()
所有引用。
通过构建时检测,您的项目用户将不需要在其类路径中包含 EA Async,除非他们也选择使用它。这意味着 EA Async不需要是传递依赖。
这是库和 Maven 项目的最佳选择。
< build >
< plugins >
< plugin >
< groupId >com.ea.async</ groupId >
< artifactId >ea-async-maven-plugin</ artifactId >
< version >1.2.3</ version >
< executions >
< execution >
< goals >
< goal >instrument</ goal >
< goal >instrument-test</ goal >
</ goals >
</ execution >
</ executions >
</ plugin >
</ plugins >
</ build >