Comment utiliser AsyncRestTemplate pour effectuer plusieurs appels simultanément?
Je ne comprends pas comment utiliser AsyncRestTemplate
efficacement pour faire les appels de service externes. Pour le code ci-dessous:
class Foo {
public void doStuff() {
Future<ResponseEntity<String>> future1 = asyncRestTemplate.getForEntity(
url1, String.class);
String response1 = future1.get();
Future<ResponseEntity<String>> future2 = asyncRestTemplate.getForEntity(
url2, String.class);
String response2 = future2.get();
Future<ResponseEntity<String>> future3 = asyncRestTemplate.getForEntity(
url3, String.class);
String response3 = future3.get();
}
}
Idéalement je veux exécuter tous les 3 appels simultanément et de traiter les résultats une fois qu'ils sont tous fait. Cependant chaque service externe appel est pas récupérés jusqu'à ce que get()
est appelée, mais get()
est bloqué. Donc n'est-elle pas à l'encontre du but de AsyncRestTemplate
? Je pourrais tout aussi bien utiliser RestTemplate
.
Donc je n'ai pas understaand comment je peux les faire exécuter simultanément?
source d'informationauteur Glide | 2016-02-05
Vous devez vous connecter pour publier un commentaire.
N'ont tout simplement pas de blocage d'appel
get()
avant l'envoi de tous vos appels asynchrones:Vous pouvez faire les deux expédition et obtenir dans les boucles, mais note que les résultats actuels de collecte est inefficace, il serait coincé sur le côté inachevé de l'avenir.
Vous pouvez ajouter tous les contrats à terme à une collection, et itérer dessus de test de chaque futur pour les non bloquant
isDone()
. Lorsque cet appel renvoie la valeur true, vous pouvez ensuite appelerget()
.De cette façon, votre en masse les résultats de la collecte sera optimisée plutôt que d'attendre sur le côté lent futur résultat dans l'ordre d'appel
get()
s.Mieux encore, vous pouvez enregistrer des fonctions de rappel (temps d'exécution) à l'intérieur de chaque
ListenableFuture
retourné parAccyncRestTemplate
et vous n'avez pas à vous soucier des variations conjoncturelles d'inspecter les résultats potentiels.Si vous n'avez pas à utiliser "AsyncRestTemplate' je suggère d'utiliser RxJava à la place. RxJava zip opérateur est ce que vous cherchez. Code de vérification ci-dessous:
Toutes les demandes de services externes seront exécutées dans des threads séparés, lors du dernier appel sera fini de la transformation de la fonction( dans l'exemple simple concaténation de chaîne) sera appliquée et le résultat (chaîne concaténée) sera emmited de 'zip' observable.
Ce que je Comprends par Votre question est que Vous avez un prédéfini méthode asynchrone et que vous essayez de faire est d'appeler cette méthode asynchoronously à l'aide de RestTemplate Classe.
J'ai écrit une méthode qui va vous aider à appeler Votre méthode asynchoronously.
Vous pouvez utiliser
CompletableFuture
classe (javadoc).Transformer vos appels en
CompletableFuture
. Par exemple.Prochain appel
CompletableFuture::allOf
méthode avec vos 3 nouvellement créé complétées à terme.Appel
join()
méthode sur le résultat. Après que la complétées avenir est résolu, vous pouvez obtenir les résultats de chaque complétées avenir que vous avez créé à l'étape 3.Je pense que vous êtes un malentendu un peu les choses ici. Lorsque vous appelez la getForEntity méthode, les demandes sont déjà tiré. Lorsque la méthode get() de l'avenir de l'objet est appelé, vous êtes en attente pour la demande de remplir. C'est dans le but de feu tous ces trois demandes sur le même subsecond, vous avez juste à faire:
Après tous ces codes sont à exécuter, toutes les demandes sont déjà inscrits (plus probablement dans la même subsecond). Ensuite, vous pouvez faire ce que vous voulez dans le même temps. Dès que vous appelez tout de la méthode get (), vous êtes en attente pour chaque demande de remplir. Si elles sont déjà terminé, il va juste retourner immédiatement.
Je ne pense pas que toutes les réponses précédentes de réaliser le parallélisme. Le problème avec @diginoise réponse est qu'il ne fait pas les atteindre parallélisme. Dès que nous appelons
get
nous sommes bloqués. Considérer que les appels sont vraiment lents tels quefuture1
prend 3 secondes pour terminer,future2
2 secondes etfuture3
3 secondes. Avec 3get
appelle l'un après l'autre, nous nous retrouvons en attente 3 + 2 + 3 = 8 secondes.@Vikrant Kashyap réponse blocs ainsi sur
while (!(future1 .isDone() && future2.isDone() && future3.isDone()))
. En plus de lawhile
boucle est assez laid à la recherche morceau de code pour les 3 contrats à terme, que si vous avez plus? @lkz réponse utilise une technologie différente que vous avez demandé, et même alors, je ne suis pas sûr sizip
va faire le travail. De Observables Javadoc:En raison du Printemps popularité, ils essaient très dur de maintenir une compatibilité ascendante et en agissant de la sorte, parfois faire des compromis avec l'API.
AsyncRestTemplate
les méthodes retournantListenableFuture
est un de ces cas. Si ils se sont engagés à Java 8+,CompletableFuture
pourrait être utilisé à la place. Pourquoi? Puisque nous ne traitant avec des pools de threads directement, nous n'avons pas une bonne façon de savoir si tous les ListenableFutures avez terminé.CompletableFuture
a unallOf
méthode qui crée une nouvelleCompletableFuture
qui est terminé lorsque toutes les CompletableFutures complète. Puisque nous n'avons pas que dansListenableFuture
nous aurons à improviser.Je n'ai pas compilé le code suivant mais il devrait être clair ce que je suis en train de faire. Je suis à l'aide de Java 8 parce que c'est la fin de l'année 2016.
Maintenant, nous avons un
Map
pour quifutures.get(Boolean.TRUE)
va nous donner tous les contrats à terme qui ont complété etfutures.get(Boolean.FALSE)
va nous donner à ceux qui n'ont pas. Nous vous souhaitez annuler ceux qui n'ont pas complète.Ce code n'est quelques choses qui sont importantes à la programmation parallèle: