WebClientd的Block和Subscribe

本文通过Java代码示例展示了WebClient在调用服务时,使用block和subscribe方法的区别。block是同步调用,会阻塞直到服务完成;而subscribe是异步调用,不会等待服务完成。实验结果显示,服务是否有返回值并不影响这一行为,block始终同步,subscribe始终异步。

探究WebClient的block和subscribe call有无return的服务的区别

Java代码

Server

Server1

@RequestMapping("/server1")
    public void server1(){
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("server1 is executing");
        }
        log.info("server1 is done");
    }

Server2

 @RequestMapping("/server2")
    public String server2(){
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("server2 is executing");
        }
        log.info("server2 is done");
        return "server2's return";
    }

Client

client1

@RequestMapping("/client1")
    public void client1() {
        log.info("block call 无return");
        Void block = webClient.get().uri("/server1").retrieve().bodyToMono(Void.class).block();
        log.info("client1 finished");
    }

client2

 @RequestMapping("/client2")
    public void client2() {
        log.info("block call 有return");
        String block = webClient.get().uri("/server2").retrieve().bodyToMono(String.class).block();
        log.info("client2 finished");
    }

client3

@RequestMapping("/client3")
    public void client3() {
        log.info("subscribe call 无return");
        Disposable subscribe = webClient.get().uri("/server1").retrieve().bodyToMono(Void.class).subscribe();
        log.info("client3 finished");
    }

client4

@RequestMapping("/client4")
    public void client4() {
        log.info("subscribe call 有return");
        Disposable subscribe = webClient.get().uri("/server2").retrieve().bodyToMono(String.class).subscribe();
        log.info("client4 finished");
    }

控制台输出

Block call 无return

在这里插入图片描述

Block call 有return

在这里插入图片描述

Subscribe call 无return

在这里插入图片描述

Subscribe call 有return

在这里插入图片描述

结论

Block同步,subscribe异步。与call的服务有没有return无关

在响应式编程中,`blockingForEach` `subscribe` 是两种不同的方式来处理数据流,它们的主要区别在于**执行方式、线程行为以及对背压的处理**。这些差异在实际开发中对程序的性能行为有重要影响。 ### 1. `blockingForEach` 的特点 `blockingForEach` 是一个阻塞式操作,它会**等待数据流中的所有元素处理完毕**后才释放当前线程。它通常用于测试或简单场景中,不适用于高并发的生产环境。 - 它会**阻塞调用线程**,直到整个流处理完成。 - 不支持异步处理,**不适用于处理大量数据或长时间运行的任务**。 - 通常用于调试或在单元测试中验证数据流内容。 例如在 Project Reactor 中使用 `blockingForEach` 的方式如下: ```java Flux.just(1, 2, 3) .blockingForEach(i -> System.out.println("Received: " + i)); ``` 此方法会逐个打印元素,**主线程被阻塞**,直到所有元素处理完成[^1]。 ### 2. `subscribe` 的特点 `subscribe` 是响应式流的标准消费方式,它是**非阻塞的**,适用于异步事件驱动的场景。 - 它不会阻塞调用线程,**数据在后台异步处理**。 - 支持背压(backpressure),允许消费者控制数据流速率。 - 可以通过 `Subscriber` 自定义对 `onNext`、`onError` `onComplete` 的处理。 例如使用 `subscribe` 的方式: ```java Flux.just(1, 2, 3) .subscribe(i -> System.out.println("Received: " + i)); ``` 此方法会立即返回,**处理在后台线程中进行**,不会阻塞主线程[^1]。 ### 3. 线程行为差异 - `blockingForEach` 在调用线程上同步执行整个流处理,**线程会被占用直到完成**。 - `subscribe` 默认在当前线程开始执行,但可以通过 `subscribeOn` `publishOn` 指定调度器,实现**多线程或异步处理**。 ### 4. 背压支持 - `blockingForEach` 不支持背压,消费者无法通知生产者减缓发送速度。 - `subscribe` 支持通过 `request(n)` 显式请求数据,实现背压控制,适用于处理高速数据流。 ### 5. 使用场景建议 - 使用 `blockingForEach` 的场景: - 简单调试或单元测试。 - 数据量小、处理时间短的场景。 - 使用 `subscribe` 的场景: - 实际生产环境中的异步流处理。 - 需要背压控制或非阻塞行为的场景。 - 构建高性能、响应式的系统。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

skye111321

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值