简体   繁体   English

从返回 mono 的方法创建通量

[英]creating a flux from a method returning mono

I learning how to change non-reactive code to reactive.我正在学习如何将非反应性代码更改为反应性代码。 As part of the exercise I took this sample code for finding primes in a range作为练习的一部分,我使用了这个示例代码来查找范围内的素数

public class FindPrime {

    private List<Integer> primes;

    public FindPrime() {
        primes = new ArrayList<>();
    }

    public List<Integer> allPrimes(int low, int high) {
        for (int i = low; i <= high; i++) {
            // skip is the number is 1
            // As 1 is neither prime nor composite
            if (i == 1) continue;

            // if the number is prime add the number to list
            if (isPrime(i) == 1) {
                primes.add(i);
            }
        }
        return primes;
    }

    private int isPrime(int n) {
        // for loop from 2 to sqrt(n)
        for (int i = 2; i <= Math.sqrt(n); i++) {
            // if the number is divisible return -1
            if (n % i == 0) {
                return -1;
            }
        }
        // return 1 if number is prime
        return 1;
    }
}

While rewriting it to reactive code I started with using Flux.fromIterbale on the List produced to return a flux, but then the code essentially is still blocking?在将其重写为反应式代码时,我开始在生成的列表上使用Flux.fromIterbale以返回通量,但代码本质上仍然是阻塞的? specially the isPrime method.特别是isPrime方法。 Hence I turned it into the following因此我把它变成了下面的

public Mono<Integer> isPrime(int n) {
    for (int i = 2; i <= Math.sqrt(n); i++) {
        // if the number is divisible return -1
        if (n % i == 0) {
            return Mono.just(-1);
        }
    }
    // return 1 if number is prime
    return Mono.just(1);
}

Which works as expected for me if I access the Mono, JitteryPrimesEmitter being the class where I have the new method如果我访问 Mono, JitteryPrimesEmitter是我有新方法的 class,这对我来说是预期的

JitteryPrimesEmitter emitter = new JitteryPrimesEmitter();
// One Value at a time
int input = 97;
new JitteryPrimesEmitter().isPrime(input)
            .filter(x -> x == 1)
            .subscribe(x -> System.out.println("Got a Prime " + input));

The next step was to emit a flux of primes, using this isPrime method, so I wrote the allPrimes method as follows下一步是使用这个isPrime方法发出质数通量,所以我编写了allPrimes方法如下

public Flux<Integer> allPrimes(int low, int high) {
    return Flux.create((FluxSink<Integer> sink) -> {
        for (int i = low; i <= high; i++) {
            // skip is the number is 1
            // As 1 is neither prime nor composite
            if (i == 1) continue;

            isPrime(i).filter(n -> n == 1)
                    .delayElement(Duration.ofMillis(new Random().nextInt(20) + 1))
                    .doOnNext(m -> System.out.println("Publishing new prime " + m + "for range " + low + "-" + high))
                    .doOnNext(sink::next);
        }
    });
}

The random delay is how I'm making it jittery to stimulate data flow from a slow I/O upstream.随机延迟是我如何让它紧张地刺激来自慢速 I/O 上游的数据流。 This doesn't work as if I call allPrimes with 10, 100 as input I see no results, here's the downstream call这不起作用,就好像我用 10、100 作为输入调用allPrimes我看不到任何结果,这是下游调用

// Flux of values
AtomicInteger sum = new AtomicInteger();
AtomicInteger highest = new AtomicInteger(0);
Flux<Integer> primesFlux = emitter.allPrimes(10, 100);
primesFlux.doOnSubscribe(s -> System.out.println("Subscribed downstream operation to primes flux"));

ConnectableFlux<Integer> primes = primesFlux.publish();
primes.doOnComplete(() -> System.out.println("Sum of Primes = " + sum.get()))
        .subscribe(i -> {
            sum.addAndGet(i);
            System.out.println("Adding emitted prime " + i + " to sum " + sum);
        });

primes.doOnComplete(() -> System.out.println("Highest Prime = " + highest.get()))
        .subscribe(i -> {
            System.out.println("Checking if " + i + " is highest prime in the range 10-100");
            highest.set(i);
        });

primes.connect();
System.out.println("Done Subscribing to Primes Flux");

Neither sum nor highest is populated, nor do I see any of the messages I'm printing in the downstream Flux pipelines, I do see that the isPrime mono method emits values as and when it's called from the allPrimes method. sumhighest都没有被填充,我也没有看到我在下游 Flux 管道中打印的任何消息,我确实看到isPrime mono 方法在从allPrimes方法调用时发出值。

Problem was my implementation of allPrimes here's the fixed version问题是我对allPrimes的实现,这里是固定版本

public Flux<Integer> allPrimes(int low, int high) {
    return Flux.range(low, high - low)
            .flatMap(it ->
                    isPrime(it).flatMap(result ->
                            result == 1 ? Mono.just(it) : Mono.empty()))
            .doOnNext(m -> System.out.println("Publishing new prime " + m + " for range " + low + "-" + high));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM