反应堆-异步/非阻塞

时间:2020-07-07 19:10:21

标签: java spring-webflux project-reactor

我认为下面的磁链将通过事件循环(如JS)放置/执行。因此,运行以下代码将首先打印阻塞的for循环,然后将执行磁链。

但是总要在移入for循环之前首先执行整个磁通。 [我确实有一些sleep语句正在阻止。但是有两个doOnNext阶段]

AtomicInteger atomicInteger = new AtomicInteger(0);

// reactor
Flux.generate(synchronousSink -> {
            if (atomicInteger.incrementAndGet() < 3) {
                synchronousSink.next(atomicInteger.get());
            } else
                synchronousSink.complete();
    })
    .doOnNext(i -> {
        System.out.println(
                "A - Received " + i + " by " + Thread.currentThread().getName()
        );
        sleep(Duration.ofSeconds(1));
    }).doOnNext(i -> {
        System.out.println(
                "B - Received " + i + " : by " + Thread.currentThread().getName()
        );
        sleep(Duration.ofSeconds(1));
    }).subscribe();


for (int i = 0; i < 5; i++) {
    System.out.println("For " + i + " by " + Thread.currentThread().getName());
    sleep(Duration.ofMillis(500));
}

它打印

A - Received 1 by main
B - Received 1 by main
A - Received 2 by main
B - Received 2 by main
For 0 by main
For 1 by main
For 2 by main
For 3 by main
For 4 by main

有人可以解释这种行为并回答这些问题吗?

  1. 当我们使用反应堆时,是否只有通过使用一些调度程序才能实现异步/非阻塞行为?
  2. 如果我不使用任何调度程序,而是让代码使用当前线程来执行代码,那么即使对于IO密集型应用程序,我们可以期望使用WebFlux而不是Spring MVC带来更好的性能差异吗?

1 个答案:

答案 0 :(得分:0)

  1. 线程阻塞不适用于Reactor使用。要使其以非阻塞方式工作,应使用publishOn / subscribeOn,然后输出应为:
For 0 by main
A - Received 1 by boundedElastic-3
For 1 by main
For 2 by main
B - Received 1 : by boundedElastic-3
For 3 by main
For 4 by main
A - Received 2 by boundedElastic-3

有关publishOnsubscribeOn的更多信息,请参见:link

  1. 可以肯定-Reactor支持HTTP(包括Websockets),TCP和UDP的非阻塞。更重要的是,Reactor默认在Netty服务器上工作,这改变了处理请求的方式。 例如,在Tomcat中,请求-响应由同一线程处理-而且该线程还在等待响应,因此被阻塞了。在Netty中,一个线程可以处理发送请求,另一个线程可以处理接收响应-线程不等待隐式的响应。