Sou desenvolvedor C # normal, mas ocasionalmente desenvolvo aplicativos em Java. Eu estou querendo saber se existe algum equivalente em Java de c # assíncrono / aguardar? Em palavras simples, qual é o equivalente java de:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
return urlContents.Length;
}
async
, mas usarFuture
ouObservable
valores.Respostas:
Não, não há equivalente a async / wait em Java - ou mesmo em C # antes da v5.
É um recurso de linguagem bastante complexo para construir uma máquina de estado nos bastidores.
Há relativamente pouco suporte à linguagem para assincronia / simultaneidade em Java, mas o
java.util.concurrent
pacote contém muitas classes úteis em torno disso. (Não é bem equivalente à Task Parallel Library, mas a aproximação mais próxima a ela.)fonte
Ele
await
usa uma continuação para executar código adicional quando a operação assíncrona for concluída (client.GetStringAsync(...)
).Portanto, como a aproximação mais próxima, eu usaria uma solução baseada em
CompletableFuture<T>
(o Java 8 equivalente a .netTask<TResult>
) para processar a solicitação Http de forma assíncrona.ATUALIZADO em 25-05-2016 para o AsyncHttpClient v.2 lançado em 13 de abril de 2016:
Portanto, o Java 8 equivalente ao exemplo de OP
AccessTheWebAsync()
é o seguinte:Esse uso foi retirado da resposta de Como obtenho um CompletableFuture de uma solicitação de cliente HTTP assíncrono? e que está de acordo com a nova API fornecida na versão 2 do AsyncHttpClient lançada em 13 de abril de 2016, que já possui suporte intrínseco
CompletableFuture<T>
.Resposta original usando a versão 1 do AsyncHttpClient:
Para esse fim, temos duas abordagens possíveis:
o primeiro usa IO sem bloqueio e eu o chamo
AccessTheWebAsyncNio
. No entanto, comoAsyncCompletionHandler
é uma classe abstrata (em vez de uma interface funcional), não podemos passar um lambda como argumento. Por isso, incorre em verbosidade inevitável devido à sintaxe de classes anônimas. No entanto, essa solução é a mais próxima do fluxo de execução do exemplo C # fornecido .o segundo é um pouco menos detalhado, no entanto, enviará uma nova tarefa que, em última análise, bloqueará um encadeamento
f.get()
até a resposta ser concluída.Primeira abordagem , mais detalhada, mas sem bloqueio:
Segunda abordagem menos detalhada, mas bloqueando um thread:
fonte
Confira o ea-async, que reescreve o bytecode Java para simular async / aguardar bastante. De acordo com o leia-me: "É fortemente inspirado pelo Async-Await no .NET CLR"
fonte
assíncrono e aguardar são açúcares sintáticos. A essência do assíncrono e da espera é a máquina de estado. O compilador transformará seu código assíncrono / aguardado em uma máquina de estado.
Ao mesmo tempo, para que o assíncrono / espera seja realmente praticável em projetos reais, precisamos ter muitas funções da biblioteca de E / S assíncrona já em funcionamento . Para C #, a maioria das funções de E / S sincronizadas originais possui uma versão Async alternativa. A razão pela qual precisamos dessas funções Async é que, na maioria dos casos, seu próprio código async / waitit se resume a algum método Async da biblioteca.
As funções da biblioteca de versões Async em C # são como o conceito AsynchronousChannel em Java. Por exemplo, temos AsynchronousFileChannel.read, que pode retornar um futuro ou executar um retorno de chamada após a conclusão da operação de leitura. Mas não é exatamente o mesmo. Todas as funções C # Async retornam Tarefas (semelhantes a Future, mas mais poderosas que Future).
Então, digamos que o Java suporte async / waitit, e escrevemos um código como este:
Então eu imagino que o compilador transformará o código async / waitit original em algo como isto:
E aqui está a implementação do AsyncHandler:
fonte
Não há equivalente a C # assíncrono / aguardado em Java no nível da linguagem. Um conceito conhecido como Fibers, também conhecido como encadeamento cooperativo ou encadernação leve, pode ser uma alternativa interessante. Você pode encontrar bibliotecas Java fornecendo suporte para fibras.
Bibliotecas Java que implementam Fibers
Você pode ler este artigo (do Quasar) para uma boa introdução às fibras. Ele cobre o que são threads, como as fibras podem ser implementadas na JVM e possui algum código específico do Quasar.
fonte
Task
classe) registrando um retorno de chamada.Como foi mencionado, não há equivalente direto, mas uma aproximação muito próxima pode ser criada com modificações de bytecode Java (para instruções assíncronas / tipo aguardar e implementação de continuações subjacentes).
Estou trabalhando agora em um projeto que implementa async / wait em cima de wait biblioteca de continuação JavaFlow , verifique https://github.com/vsilaev/java-async-await
Nenhum Maven mojo foi criado ainda, mas você pode executar exemplos com o agente Java fornecido. Aqui está como é o código assíncrono / aguardado:
@async é a anotação que sinaliza um método como executável de forma assíncrona, waitit () é uma função que espera no CompletableFuture usando continuações e uma chamada para "retornar asyncResult (someValue)" é o que finaliza o CompletableFuture / Continuation associado
Assim como no C #, o fluxo de controle é preservado e o tratamento de exceções pode ser feito de maneira regular (tentativa / captura como no código executado sequencialmente)
fonte
O próprio Java não possui recursos equivalentes, mas existem bibliotecas de terceiros que oferecem funcionalidade semelhante, por exemplo, Kilim .
fonte
Primeiro, entenda o que é assíncrono / espera. É uma maneira de um aplicativo GUI de thread único ou um servidor eficiente executar várias "fibras" ou "co-rotinas" ou "threads leves" em um único thread.
Se você concorda com o uso de encadeamentos comuns, o equivalente em Java é
ExecutorService.submit
eFuture.get
. Isso bloqueará até que a tarefa seja concluída e retorne o resultado. Enquanto isso, outros threads podem funcionar.Se você deseja o benefício de algo como fibras, precisa de suporte no contêiner (quero dizer no loop de eventos da GUI ou no manipulador de solicitações HTTP do servidor), ou escrevendo seu próprio.
Por exemplo, o Servlet 3.0 oferece processamento assíncrono. Ofertas JavaFX
javafx.concurrent.Task
. Porém, eles não têm a elegância dos recursos de idioma. Eles trabalham com retornos de chamada comuns.fonte
Não há nada nativo no java que permita fazer isso como palavras-chave assíncronas / aguardadas, mas o que você pode fazer se realmente quiser é usar um CountDownLatch . Você pode imitar async / wait passando isso (pelo menos em Java7). Essa é uma prática comum nos testes de unidade do Android, onde temos que fazer uma chamada assíncrona (geralmente uma executável postada por um manipulador) e aguardar o resultado (contagem regressiva).
No entanto, usar isso dentro do aplicativo em oposição ao seu teste NÃO é o que estou recomendando. Isso seria extremamente péssimo, pois o CountDownLatch depende de você contar efetivamente o número certo de vezes e nos lugares certos.
fonte
Crio e liberei a biblioteca Java async / waitit. https://github.com/stofu1234/kamaitachi
Essa biblioteca não precisa da extensão do compilador e realiza o processamento de E / S sem pilha em Java.
↓
fonte
Infelizmente, o Java não tem equivalente de assíncrono / espera. O mais próximo que você pode chegar é provavelmente o ListenableFuture da Guava e o encadeamento do ouvinte, mas ainda seria muito complicado escrever para casos que envolvam várias chamadas assíncronas, pois o nível de aninhamento aumentaria muito rapidamente.
Se você está bem com o uso de um idioma diferente na JVM, felizmente existe o recurso assíncrono / aguardado no Scala, que é um equivalente C # assíncrono / aguardado direto com uma sintaxe e semântica quase idênticas: https://github.com/scala/ assíncrono /
Observe que, embora essa funcionalidade precise de um suporte de compilador bastante avançado em C #, no Scala, ela pode ser adicionada como uma biblioteca, graças a um sistema de macros muito poderoso no Scala e, portanto, pode ser adicionada até a versões mais antigas do Scala, como a 2.10. Além disso, o Scala é compatível com classe com Java, portanto, você pode escrever o código assíncrono no Scala e depois chamá-lo de Java.
Há também outro projeto semelhante chamado Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html que usa palavras diferentes, mas conceitualmente é muito semelhante, porém implementado usando continuações delimitadas, não macros (por isso funciona com versões Scala ainda mais antigas, como 2.9).
fonte
Java não possui equivalente direto ao recurso da linguagem C # chamado async / waitit, no entanto, existe uma abordagem diferente para o problema que o async / waitit tenta resolver. Chama-se projeto Loom , que fornecerá threads virtuais para simultaneidade de alto rendimento. Ele estará disponível em alguma versão futura do OpenJDK.
Essa abordagem também resolve o " problema da função colorida " que o async / waitit possui.
Recurso semelhante também pode ser encontrado em Golang ( goroutines ).
fonte
Se você está logo após um código limpo que simula o mesmo efeito que assíncrono / aguardar em java e não se importa de bloquear o encadeamento em que é chamado até terminar, como em um teste, você pode usar algo como este código:
fonte
A biblioteca Java AsynHelper inclui um conjunto de classes / métodos utilitários para chamadas assíncronas (e espera).
Se desejar executar um conjunto de chamadas de método ou blocos de código de forma assíncrona, ele inclui um método auxiliar útil AsyncTask .submitTasks, como no snippet abaixo.
Se desejar aguardar até que todos os códigos assíncronos sejam executados, o variante AsyncTask.submitTasksAndWait pode ser usado.
Além disso, se desejar obter um valor de retorno de cada chamada de método assíncrona ou bloco de código, o AsyncSupplier .submitSuppliers pode ser usado para que o resultado possa ser obtido pela matriz de fornecedores de resultados retornada pelo método. Abaixo está o snippet de amostra:
Se o tipo de retorno de cada método for diferente, use o tipo de trecho abaixo.
O resultado do método assíncrono de chamadas / blocos de código também pode ser obtido em um ponto de código diferente no mesmo thread ou em um thread diferente do snippet abaixo.
fonte