我知道Mono.defer()
是做什么的,但是我应该什么时候使用它呢?我知道其中一个用例是推迟返回Mono
的函数中的一些阻塞副作用,但这通常是一个糟糕的做法(将副作用放在返回Mono
或Flux
的函数中)。当我想在Mono
中包装一些阻塞代码时,可以使用Mono.fromCallable()
。那么使用Mono.defer()
的最佳案例是什么呢?
发布于 2021-07-14 23:28:08
Mono.fromCallable()
用于常规延迟服务调用。Mono.defer()
会生成一个Mono
,只有当您订阅时它才会这样做。因此,您可能决定不在合成阶段创建此Mono
,而是完全在目标订阅者上创建。
发布于 2021-11-14 23:16:07
@a.khakh
帮助我的一个非常简单的用例是在另一个线程中执行阻塞代码,即处理那个阻塞调用,这样主线程就不会阻塞我。
我发现需要在另一个线程中使用defer进行订阅,在本例中是在project reactor提供的、由Simon Basle编程的Scheduler中。
如果你使用defer
+ subscribeOn
和Schedulers.boundedElastic
的组合,你将使你的代码是非阻塞的,或者更确切地说,它不会阻塞你的应用程序,从而消除主线程的争用。
下图显示了Combo的第三个组件在内部使用了defer和Scheduler,这样就不会阻塞应用程序。
ui.access()
的方法,它是vaadin框架的一部分。Mono.defer(() -> this.reactiveRandomNumbers.monoFrecuency(event.getValue().getSize())) <1>
.doOnEach(signal -> log.info("Thread name doOnNext(): {}", Thread.currentThread().getName()))
.subscribeOn(Schedulers.boundedElastic())
.subscribe(subscribeMap -> {
ui.access(() -> {
log.info("Thread name subscribe(): {}", Thread.currentThread().getName());
this.execute(event.getValue().getSize(), e -> subscribeMap);
});
});
发布于 2021-11-23 20:25:26
有时你需要懒惰地计算一些同步的东西。
例如,我们有一个异步服务
public interface SomeService {
Mono<User> getUserByName(String name);
Mono<CreateUserResult> createUser(User user);
}
以及一个端点,它在此服务中查找用户,如果没有找到,则创建该端点。但在创建之前,必须在特殊的线程池中同步执行一些繁重的计算。所以
someService.getUserByName(name)
.switchIfEmpty(Mono.defer(() -> {
var someHeavyCalculatedData = localHeavyService.doSomethingNecessary(name);
return someService.createUser(new User(name, someHeavyCalculatedData));
}).subscribeOn(specialScheduler));
当然,您可以说我们可以使用Mono.fromCallable
,并像这样做
someService.getUserByName(name)
.switchIfEmpty(Mono.fromCallable(() -> localHeavyService.doSomethingNecessary(name))
.subscribeOn(specialScheduler)
.flatMap(someHeavyCalculatedData -> someService.createUser(new User(name, someHeavyCalculatedData)))
);
但是,反应链中的每个方法调用都会导致在内存中创建大量对象。好吧,对于一个单独的调用,你可能不会注意到任何东西,但随着更高的负载频繁地分配内存,然后由GC释放它会导致你的应用程序变慢。
https://stackoverflow.com/questions/68379116
复制相似问题