简体   繁体   English

如何在 Java 的异步方法中调用同步阻塞方法?

[英]How to call Synchronus blocking method inside async method in Java?

I'm Using Project Reactor library.我正在使用 Project Reactor 库。 Here is my scenario.这是我的场景。

I want to call the blocking service inside my non blocking method.我想在我的非阻塞方法中调用阻塞服务。

I have a three different services, I called those three services from my springboot application.我有三个不同的服务,我从我的 springboot 应用程序中调用了这三个服务。 Here is my sample code这是我的示例代码

public Mono<Example> getValuesFromDifferentServices() {

  Mono<Example1> mono1=service.getService1();
  Mono<Example2> mono2=service.getService2();

  mono1.zipwith(mono2)
     .map(value-> {
         // some logics then
         if(value.getT1().getStatus().equals(value.getT2().getStatus())) {
           Mono<Example3> mono3 = service.getService3(true);
           mono3.map(f-> {
              value.getT1().setSomething(f.getSomething);
              return f;
           }).subscribe();
         }
       return value.getT1();
     })
}

Note: Above example is not the actual logic.注意:上面的例子不是实际的逻辑。 But the implementation is similar to that但实现类似于

Even I tried to subscribe() it, I couldn't get the 3rd service value all the time (uncertainty values).即使我尝试subscribe()它,我也无法始终获得第三个服务值(不确定性值)。 I cannot block() the 3rd service since it is not allowed.我不能block()第三个服务,因为它是不允许的。 How to achieve this?如何做到这一点?

Update: 3rd Service input would be decided after If condition either it should be true or not Mono<Example3> mono3 = service.getService3(true);更新:第 3 个服务输入将在 If 条件是否为真之后决定Mono<Example3> mono3 = service.getService3(true); We should call the 3rd service if only the condition matches, otherwise calling the 3rd service is not required and which is not advisable., If condition doesn't match, we should not invoke 3rd service.如果只有条件匹配我们应该调用第三服务,否则不需要调用第三服务,这是不可取的。如果条件不匹配,我们不应该调用第三服务。

This example is a little wierd but as I understand, you want to call the first two services, each give you back a single value.这个例子有点奇怪,但据我所知,你想调用前两个服务,每个服务都给你一个值。 After that you want to call the third one if necessary and set a value from this into one of the first's field.之后,如果需要,您想调用第三个并将此值设置为第一个字段之一。

Anyway, there is a simple solution, but with more information maybe we can create nicer stream.无论如何,有一个简单的解决方案,但有了更多信息,也许我们可以创建更好的 stream。 This stream takes adventages of flatMap, which eagerly subscribes into the inner publisher.这个 stream 采用了 flatMap 的优点,它急切地订阅了内部发布者。

[The example was written in Kotlin, it's very like Java. [例子写在Kotlin,很像Java。 The only confusig thing here maybe the it variable, which is equals something like this: map(it -> it.sg ) ]这里唯一混淆的东西可能是it变量,它等于这样的东西: map(it -> it.sg ) ]

data class Example(
    val name: String,
    val status: String,
    var value: String? = null  
)

class ReactorTest {

    @Test
    fun test() {
        val first = Mono.just(Example("first", "suspended"))
        val second = Mono.just(Example("second", "suspended"))
        val third = Mono.just(Example("third", "suspended", "thirdValue"))

        val stream = first.zipWith(second)
            .flatMap { tuple ->
                Mono.just(tuple.t1)
                    .filter { it.status == tuple.t2.status }
                    .zipWith(third)
                    .doOnNext {
                        it.t1.value = it.t2.value
                    }
                    .map { it.t1 }
                    .switchIfEmpty(Mono.just(tuple.t1))
            }

            StepVerifier.create(stream)
                .expectNext(Example("first", "suspended", "thirdValue"))
                .verifyComplete()
    }

    @Test
    fun test2() {
        val first = Mono.just(Example("first", "suspended"))
        val second = Mono.just(Example("second", "active"))
        val third = Mono.just(Example("third", "suspended", "thirdValue"))

        val stream = first.zipWith(second)
            .flatMap { tuple ->
                Mono.just(tuple.t1)
                    .filter { it.status == tuple.t2.status }
                    .zipWith(third)
                    .doOnNext {
                        it.t1.value = it.t2.value
                    }
                    .map { it.t1 }
                    .switchIfEmpty(Mono.just(tuple.t1))
            }

        StepVerifier.create(stream)
            .expectNext(Example("first", "suspended"))
            .verifyComplete()
    }
}

Side note: if you're using blocking services in your reactive streams, those should be separated into dedicated threadpools.旁注:如果您在反应流中使用阻塞服务,则应将它们分离到专用线程池中。 Like:喜欢:

fun blockingService(): Mono<String> {
    //real service use fromCallable
    return Mono.just("fromCallableOnServiceCall")
        //for real service it may use a dedicated pool
        .subscribeOn(Schedulers.boundedElastic())

}

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

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