2015-03-09 2 views
4

pouvant être complétée Mon problème est de savoir comment utiliser l'avenir pouvant être complétée.Java 8 Future

J'ai une classe qui implémente appelable.

public class Executor implements Callable<Collection> 

Un peu plus tôt est utilisé pour faire -

service.submit(collectorService); 

Ce qui renverrait une Future<Collection>. Cependant, nous ne voulons plus utiliser le futur et avons besoin de CompletableFuture. Une idée est que nous n'avons pas besoin d'interroger CompletableFuture et nous ne devons pas attendre et bloquer jusqu'à ce qu'il soit prêt.

Alors, comment pourrais-je utiliser future future et appeler une fonction dire isDone() lorsque le fil callable se termine.

+0

Peut-être intéressant pour vous: http://stackoverflow.com/questions/23301598/transform-java-future-into-a-completablefuture – GPI

+1

"nous ne voulons plus utiliser le futur et besoin de' CompletableFuture' "- intéressant mélange de "vouloir" et "besoin". Ne semble pas une décision rationnelle pour moi ... – Holger

+1

@Holger: d'accord avec vous. Devrais reformuler mes mots. Nous avions mis en œuvre future mais semble l'équipe qui consommerait notre code ne veut pas faire un sondage de Future.isDone() et serait donc nous tenons à fournir CompletableFuture ayush

Répondre

5

Compte tenu d'un CompletableFuture<T> f, vous pouvez lancer une tâche synchrone ou asynchrone pour exécuter à la fin en utilisant:

f.thenApply(result -> isDone(result));  // sync callback 
f.thenApplyAsync(result -> isDone(result)); // async callback 

... ou, si vous n'avez pas besoin du résultat:

f.thenRun(() -> isDone()); 
f.thenRunAsync(() -> isDone()); 
+0

Désolé pour demander plus, mais comment puis-je envoyer mes objets de classe Executor à l'intérieur des fonctions thenApply. À quoi renvoie l'objet résultat ici? – ayush

+1

Le '' consommateur passé à 'thenAccept [Async]' est un rappel qui fonctionne sur le résultat de la tâche, donc 'result' se réfère au résultat de l'avenir' f'. Dans votre exemple original, ce serait une 'Collection'.Vous pouvez référencer n'importe quelle référence 'final' (ou" effectivement final ") depuis votre callback lamda, y compris votre exécuteur, si vous voulez soumettre une autre tâche dans votre callback. –

1

Si je vous comprends bien, vous voulez savoir comment soumettre une "tâche" (votre précédent "Executor") qui rend un CompletableFuture.

Vous faites cela en appelant

CompletableFuture.supplyAsync(collectorService) 

La différence est que votre « Exécuteur » doit mettre en œuvre maintenant fournisseur au lieu de appelable

+1

Oui, le collectorService peut également être enveloppé dans une expression lambda fournisseur si la modification de la source n'est pas une option. par exemple. CompletableFuture.supplyAsync (() -> collectorService.call()) –

+0

@JohnMcClean Je pense que votre commentaire est la meilleure réponse et je pense que vous devriez en faire une réponse réelle. – aalku

+0

@aalku sûr, ajouté une réponse spécifique avec plus de détails. –

2

Vous pouvez créer une expression lambda qui appelle votre collectorService existante. Une expression lambda fournisseur qui CompletableFuture.supplyAsync acceptera ressemblerait à quelque chose comme ça

Supplier<Collection> supplier =() -> collectorService.call(); 

et peut être utilisé avec le CompletableFuture comme suit

CompletableFuture.supplyAsync(() -> collectorService.call(),service) 
     .thenApply(collection->isDone(collection); 

Comme d'autres l'ont souligné le thenApply sera exécuté lorsque le La méthode collectorService.call() renvoie un résultat - sur le même thread qui a exécuté notre tâche Future. L'utilisation de thenApplyAsync renverrait une autre tâche à un service d'exécution (la performance brute est plus lente d'environ un ordre de grandeur, donc ne le faites pas à moins d'avoir une bonne raison!).