web-dev-qa-db-fra.com

Différence entre Flux.create et Flux.generate

Quelle est la différence entre Flux.create et Flux.generate ? Je cherche - idéalement avec un exemple d'utilisation - à comprendre quand je dois utiliser l'un ou l'autre.

15
JJ Zabkar

En bref:

Flux::create Ne réagit pas aux modifications de l'état de l'application alors que Flux::generate Le fait.


La version longue

Flux::create

Vous l'utiliserez lorsque vous souhaitez calculer plusieurs valeurs (0 ... infini) qui ne sont pas influencées par l'état de votre application et l'état de votre pipeline (votre pipeline == la chaîne d'opérations qui vient après Flux::create == en aval ).

Pourquoi? Parce que la méthode que vous avez envoyée à Flux::create Continue de calculer les éléments (ou aucun). Le en aval déterminera le nombre d'éléments (éléments == prochains signaux ) il veut et s'il ne peut pas suivre, les éléments qui sont déjà émis seront supprimés/tamponnés dans une certaine stratégie (par défaut, ils seront tamponnés jusqu'à ce que en aval vous en demandera plus).

Le premier et le plus simple cas d'utilisation consiste à émettre des valeurs que vous pourriez théoriquement additionner à une collection et ensuite seulement prendre chaque élément et en faire quelque chose:

Flux<String> articlesFlux = Flux.create((FluxSink<String> sink) -> {
    /* get all the latest article from a server and
       emit them one by one to downstream. */
    List<String> articals = getArticalsFromServer();
    articals.forEach(sink::next);
});

Comme vous pouvez le voir, Flux.create Est utilisé pour l'interaction entre la méthode de blocage (getArticalsFromServer) et le code asynchrone.

Je suis sûr qu'il existe d'autres cas d'utilisation pour Flux.create.


Flux::generate

Flux.generate((SynchronousSink<Integer> synchronousSink) -> {
        synchronousSink.next(1);
    })
    .doOnNext(number -> System.out.println(number))
    .doOnNext(number -> System.out.println(number + 4))
    .subscribe();

La sortie sera 1 5 1 5 1 5................forever

Dans chaque appel de la méthode que vous avez envoyée à Flux::generate, synchronousSink ne peut qu'émettre: onSubscribe onNext? (onError | onComplete)?.

Cela signifie que Flux::generatecalculera et émettra valeurs sur demande. Quand devriez-vous l'utiliser? Dans les cas où il est trop coûteux de calculer des éléments qui ne peuvent pas être utilisés en aval ou les événements que vous émettez sont influencés par l'état de l'application ou par le l'état de votre pipeline (votre pipeline == la chaîne d'opérations qui vient après Flux::create == en aval ).

Par exemple, si vous construisez une application torrent, vous recevez des blocs de données en temps réel. Vous pouvez utiliser Flux::generate Pour donner des tâches (blocs à télécharger) à plusieurs threads et vous calculerez le bloc que vous souhaitez télécharger à l'intérieur de Flux::generate Uniquement lorsque certains threads le demandent. Vous n'émettrez donc que des blocs que vous n'avez pas. Le même algorithme avec Flux::create Échouera car Flux::create Émettra tous les blocs que nous n'avons pas et si certains blocs n'ont pas pu être téléchargés, nous avons un problème. car Flux::create ne réagit pas aux changements d'état de l'application alors que Flux::generate le fait.

16
Stav Alfi