我是一名普通的C#开发人员,但偶尔也会用Java开发应用程序.我想知道是否有任何Java等价的C#async/await?简单来说,java的等价物是什么:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
return urlContents.Length;
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 123
不,在Java中没有任何等效的async/await - 甚至在v5之前的C#中也没有.
在幕后构建状态机是一种相当复杂的语言功能.
Java中对异步/并发的语言支持相对较少,但该java.util.concurrent
软件包包含许多有用的类.(不完全等同于任务并行库,但最接近它.)
Mig*_*boa 35
在await
使用一个延续异步操作完成时执行的附加代码(client.GetStringAsync(...)
).
因此,作为最接近的近似,我将使用CompletableFuture<T>
(基于Java 8等效于.net Task<TResult>
)的解决方案来异步处理Http请求.
2016年5月25日更新至2016年4月13日发布的AsyncHttpClient v.2:
所以Java 8相当于OP的例子AccessTheWebAsync()
如下:
CompletableFuture<Integer> AccessTheWebAsync()
{
AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
return asyncHttpClient
.prepareGet("http://msdn.microsoft.com")
.execute()
.toCompletableFuture()
.thenApply(Response::getResponseBody)
.thenApply(String::length);
}
Run Code Online (Sandbox Code Playgroud)
这个用法取自如何从Async Http Client请求获取CompletableFuture的答案?
这是根据2016年Abril发布的AsyncHttpClient第2版中提供的新API ,已经具有内在的支持CompletableFuture<T>
.
使用AsyncHttpClient版本1的原始答案:
为此,我们有两种可能的方法:
第一个使用非阻塞IO,我称之为AccessTheWebAsyncNio
.然而,因为它AsyncCompletionHandler
是一个抽象类(而不是功能接口),我们不能将lambda作为参数传递.因此,由于匿名类的语法,它会导致不可避免的冗长.但是,此解决方案最接近给定C#示例的执行流程.
第二个稍微不那么详细,但它会提交一个新的任务,最终将阻止一个线程,f.get()
直到响应完成.
第一种方法,更详细但非阻塞:
static CompletableFuture<Integer> AccessTheWebAsyncNio(){
final AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
final CompletableFuture<Integer> promise = new CompletableFuture<>();
asyncHttpClient
.prepareGet("https://msdn.microsoft.com")
.execute(new AsyncCompletionHandler<Response>(){
@Override
public Response onCompleted(Response resp) throws Exception {
promise.complete(resp.getResponseBody().length());
return resp;
}
});
return promise;
}
Run Code Online (Sandbox Code Playgroud)
第二种方法不那么冗长,但阻止一个线程:
static CompletableFuture<Integer> AccessTheWebAsync(){
try(AsyncHttpClient asyncHttpClient = new AsyncHttpClient()){
Future<Response> f = asyncHttpClient
.prepareGet("https://msdn.microsoft.com")
.execute();
return CompletableFuture.supplyAsync(
() -> return f.join().getResponseBody().length());
}
}
Run Code Online (Sandbox Code Playgroud)
小智 15
async和await是语法糖.异步和等待的本质是状态机.编译器会将您的异步/等待代码转换为状态机.
同时,为了使async/await在实际项目中真正切实可行,我们需要有许多Async I/O库函数.对于C#,大多数原始同步I/O函数都有一个备用的Async版本.我们需要这些异步函数的原因是因为在大多数情况下,您自己的异步/等待代码将归结为某些库的异步方法.
C#中的Async版本库函数有点像Java中的AsynchronousChannel概念.例如,我们有AsynchronousFileChannel.read,它可以在读操作完成后返回Future或执行回调.但它并不完全相同.所有C#Async函数都返回Tasks(类似于Future,但比Future更强大).
那么让我们说Java支持async/await,我们编写一些这样的代码:
public static async Future<Byte> readFirstByteAsync(String filePath) {
Path path = Paths.get(filePath);
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(100_000);
await channel.read(buffer, 0, buffer, this);
return buffer.get(0);
}
Run Code Online (Sandbox Code Playgroud)
然后我想象编译器会将原始的async/await代码转换成如下代码:
public static Future<Byte> readFirstByteAsync(String filePath) {
CompletableFuture<Byte> result = new CompletableFuture<Byte>();
AsyncHandler ah = new AsyncHandler(result, filePath);
ah.completed(null, null);
return result;
}
Run Code Online (Sandbox Code Playgroud)
这是AsyncHandler的实现:
class AsyncHandler implements CompletionHandler<Integer, ByteBuffer>
{
CompletableFuture<Byte> future;
int state;
String filePath;
public AsyncHandler(CompletableFuture<Byte> future, String filePath)
{
this.future = future;
this.state = 0;
this.filePath = filePath;
}
@Override
public void completed(Integer arg0, ByteBuffer arg1) {
try {
if (state == 0) {
state = 1;
Path path = Paths.get(filePath);
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(100_000);
channel.read(buffer, 0, buffer, this);
return;
} else {
Byte ret = arg1.get(0);
future.complete(ret);
}
} catch (Exception e) {
future.completeExceptionally(e);
}
}
@Override
public void failed(Throwable arg0, ByteBuffer arg1) {
future.completeExceptionally(arg0);
}
}
Run Code Online (Sandbox Code Playgroud)
如前所述,没有直接的等价物,但可以使用Java字节码修改创建非常接近的近似值(对于async/await-like指令和底层延续实现).
我正在开发一个在JavaFlow连续库上实现async/await的项目,请查看https://github.com/vsilaev/java-async-await
尚未创建Maven mojo,但您可以使用提供的Java代理运行示例.以下是async/await代码的样子:
public class AsyncAwaitNioFileChannelDemo {
public static void main(final String[] argv) throws Exception {
...
final AsyncAwaitNioFileChannelDemo demo = new AsyncAwaitNioFileChannelDemo();
final CompletionStage<String> result = demo.processFile("./.project");
System.out.println("Returned to caller " + LocalTime.now());
...
}
public @async CompletionStage<String> processFile(final String fileName) throws IOException {
final Path path = Paths.get(new File(fileName).toURI());
try (
final AsyncFileChannel file = new AsyncFileChannel(
path, Collections.singleton(StandardOpenOption.READ), null
);
final FileLock lock = await(file.lockAll(true))
) {
System.out.println("In process, shared lock: " + lock);
final ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.size());
await( file.read(buffer, 0L) );
System.out.println("In process, bytes read: " + buffer);
buffer.rewind();
final String result = processBytes(buffer);
return asyncResult(result);
} catch (final IOException ex) {
ex.printStackTrace(System.out);
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
@async是将方法标记为异步可执行的注释,await()是一个使用continuation等待CompletableFuture并调用"return asyncResult(someValue)"的函数,最终确定相关的CompletableFuture/Continuation
与C#一样,控制流程被保留,异常处理可以以常规方式完成(尝试/捕获,如顺序执行的代码)
首先,了解什么是 async/await。它是单线程 GUI 应用程序或高效服务器在单个线程上运行多个“纤程”或“协程”或“轻量级线程”的一种方式。
如果您可以使用普通线程,那么 Java 等价物是ExecutorService.submit
和Future.get
。这将阻塞直到任务完成,并返回结果。同时,其他线程可以工作。
如果您想获得纤程之类的好处,您需要容器中的支持(我的意思是在 GUI 事件循环或服务器 HTTP 请求处理程序中),或者通过编写自己的。
例如,Servlet 3.0 提供异步处理。JavaFX 提供javafx.concurrent.Task
. 但是,这些没有语言功能的优雅。它们通过普通回调工作。
Java 没有直接等效的 C# 语言功能称为 async/await,但是 async/await 尝试解决的问题有不同的方法。它被称为Loom项目,它将为高吞吐量并发提供虚拟线程。它将在 OpenJDK 的某些未来版本中可用。
这种方法也解决了 async/await 的“有色函数问题”。
在 Golang ( goroutines ) 中也可以找到类似的功能。
小智 5
EA 开发了一个“等效的”await: https: //github.com/Electronicarts/ea-async。参考Java示例代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
79087 次 |
最近记录: |