{"id":10006308,"date":"2022-08-24T15:53:46","date_gmt":"2022-08-24T07:53:46","guid":{"rendered":"https:\/\/ityet.com\/?p=10006308"},"modified":"2022-08-24T15:53:46","modified_gmt":"2022-08-24T07:53:46","slug":"reactor-%e4%b9%8b-%e5%a4%9a%e4%bb%bb%e5%8a%a1%e5%b9%b6%e5%8f%91%e6%89%a7%e8%a1%8c%ef%bc%8c%e7%bb%93%e6%9e%9c%e6%8c%89%e9%a1%ba%e5%ba%8f%e8%bf%94%e5%9b%9e%e7%ac%ac%e4%b8%80%e4%b8%aa","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006308","title":{"rendered":"Reactor \u4e4b \u591a\u4efb\u52a1\u5e76\u53d1\u6267\u884c\uff0c\u7ed3\u679c\u6309\u987a\u5e8f\u8fd4\u56de\u7b2c\u4e00\u4e2a"},"content":{"rendered":"<h2>1 \u573a\u666f<\/h2>\n<p>\u8c03\u7528\u591a\u4e2a\u5e73\u7ea7\u670d\u52a1\uff0c\u6309\u7167\u670d\u52a1\u4f18\u5148\u7ea7\u8fd4\u56de\u7b2c\u4e00\u4e2a\u6709\u6548\u6570\u636e\u3002<\/p>\n<p>\u5177\u4f53case\uff1a\u4e00\u4e2a\u9875\u9762\u53ef\u80fd\u6709\u5f88\u591a\u7684\u5f39\u7a97\uff0c\u5f39\u7a97\u4e4b\u95f4\u53c8\u6709\u4f18\u5148\u7ea7\u3002\u6bcf\u6b21\u53ea\u9700\u8981\u8fd4\u56de\u7b2c\u4e00\u4e2a\u6709\u6570\u636e\u7684\u5f39\u7a97\u3002\u4f46\u662f\u53c8\u5e0c\u671b\u6240\u6709\u5f39\u7a97\u4e4b\u95f4\u7684\u6570\u636e\u83b7\u53d6\u662f\u5f02\u6b65\u7684\u3002\u8fd9\u79cd\u573a\u666f\u4f7f\u7528 Reactor \u600e\u4e48\u5b9e\u73b0\u5462\uff1f<\/p>\n<h2>2 \u521b\u5efa service<\/h2>\n<h2>2.1 \u521b\u5efa\u57fa\u672c\u63a5\u53e3\u548c\u5b9e\u4f53\u7c7b<\/h2>\n<pre><code class=\"java\">public interface TestServiceI {\n    Mono request();\n}<\/code><\/pre>\n<p>\u63d0\u4f9b\u4e00\u4e2a request \u65b9\u6cd5\uff0c\u8fd4\u56de\u4e00\u4e2a Mono \u5bf9\u8c61\u3002<\/p>\n<pre><code class=\"java\">@Data\n@ToString\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TestUser {\n    private String name;\n}<\/code><\/pre>\n<h3>2.2 \u521b\u5efa service \u5b9e\u73b0<\/h3>\n<pre><code class=\"java\">@Slf4j\npublic class TestServiceImpl1 implements TestServiceI {\n    @Override\n    public Mono request() {\n        log.info(&quot;execute.test.service1&quot;);\n        return Mono.fromSupplier(() -&gt; {\n                    try {\n                        System.out.println(&quot;service1.threadName=&quot; + Thread.currentThread().getName());\n                        Thread.sleep(500);\n                    } catch (InterruptedException e) {\n                        throw new RuntimeException(e);\n                    }\n                    return &quot;&quot;;\n                })\n                .map(name -&gt; {\n                    return new TestUser(name);\n                });\n    }\n}<\/code><\/pre>\n<p>\u7b2c\u4e00\u4e2a service \u6267\u884c\u8017\u65f6 500ms\u3002\u8fd4\u56de\u7a7a\u5bf9\u8c61\uff1b<\/p>\n<p>\u521b\u5efa\u7b2c\u4e8c\u4e2a service \u6267\u884c\u8017\u65f6 1000ms\u3002\u8fd4\u56de\u7a7a\u5bf9\u8c61\uff1b\u4ee3\u7801\u5982\u4e0a\uff0c\u6539\u4e00\u4e0bsleep\u65f6\u95f4\u5373\u53ef\u3002<\/p>\n<p>\u7ee7\u7eed\u521b\u5efa\u7b2c\u4e09\u4e2a service \u6267\u884c\u8017\u65f6 1000ms\u3002\u8fd4\u56de name3\u3002\u4ee3\u7801\u5982\u4e0a\uff0c\u6539\u4e00\u4e0b sleep \u65f6\u95f4\uff0c\u4ee5\u53ca\u8fd4\u56de\u4e3a name3\u3002<\/p>\n<h2>3 \u4e3b\u4f53\u65b9\u6cd5<\/h2>\n<pre><code class=\"java\">public static void main(String[] args) {\n        long startTime = System.currentTimeMillis();\n        TestServiceI testServiceImpl4 = new TestServiceImpl4();\n        TestServiceI testServiceImpl5 = new TestServiceImpl5();\n        TestServiceI testServiceImpl6 = new TestServiceImpl6();\n        List&lt;TestServiceI&gt; serviceIList = new ArrayList&lt;&gt;();\n        serviceIList.add(testServiceImpl4);\n        serviceIList.add(testServiceImpl5);\n        serviceIList.add(testServiceImpl6);\n\n    \/\/ \u6267\u884c service \u5217\u8868\uff0c\u8fd9\u6837\u6709\u591a\u5c11\u4e2a service \u90fd\u53ef\u4ee5\n        Flux&lt;Mono&lt;TestUser&gt;&gt; monoFlux = Flux.fromIterable(serviceIList)\n                .map(service -&gt; {\n                    return service.request();\n                });\n\n    \/\/ flatMap(\u6216\u8005flatMapSequential) + map \u5b9e\u73b0\u5f02\u5e38\u7ee7\u7eed\u4e0b\u4e00\u4e2a\u6267\u884c\n        Flux flux = monoFlux.flatMapSequential(mono -&gt; {\n            return mono.map(user -&gt; {\n                        TestUser testUser = JsonUtil.parseJson(JsonUtil.toJson(user), TestUser.class);\n                        if (Objects.nonNull(testUser) &amp;&amp; StringUtils.isNotBlank(testUser.getName())) {\n                            return testUser;\n                        }\n            \/\/ null \u5728 reactor \u4e2d\u662f\u5f02\u5e38\u6570\u636e\u3002\n                        return null;\n                    })\n                    .onErrorContinue((err, i) -&gt; {\n                        log.info(&quot;onErrorContinue={}&quot;, i);\n                    });\n        });\n        Mono mono = flux.elementAt(0, Mono.just(&quot;&quot;));\n        Object block = mono.block();\n        System.out.println(block + &quot;blockFirst \u6267\u884c\u8017\u65f6ms\uff1a&quot; + (System.currentTimeMillis() - startTime));\n    }<\/code><\/pre>\n<p>1\u3001Flux.fromIterable \u6267\u884c service \u5217\u8868\uff0c\u53ef\u4ee5\u968f\u610f\u589e\u5220 service \u670d\u52a1\u3002<\/p>\n<p>2\u3001flatMap(\u6216\u8005flatMapSequential) + map + onErrorContinue \u5b9e\u73b0\u5f02\u5e38\u7ee7\u7eed\u4e0b\u4e00\u4e2a\u6267\u884c\u3002\u5177\u4f53\u53c2\u8003\uff1a<\/p>\n<p><a href=\"https:\/\/link.segmentfault.com\/?enc=GNUc2JhfABa8Kcu6DBXUEA%3D%3D.bSPQgaCywsX%2FYqnGKSlA3AtCCuOe0Bm%2Bx8znzjrTqu7ujVkWK25uhAJOib1OCSFE1zW70Wf5aob57u68arcYw6EMzIh8clybHF4Fg%2Bvm1NGrff5%2F49Yogb%2FhC2jfbzXb\" rel=\"nofollow\">Reactor \u4e4b onErrorContinue \u548c onErrorResume<\/a><\/p>\n<p>3\u3001Mono mono = flux.elementAt(0, Mono.just(&#8220;&#8221;)); \u8fd4\u56de\u7b2c\u4e00\u4e2a\u6b63\u5e38\u6570\u636e\u3002<\/p>\n<p>\u6267\u884c\u8f93\u51fa\uff1a<\/p>\n<pre><code>20:54:26.512 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework\n20:54:26.553 [main] INFO com.geniu.reactor.TestServiceImpl1 - execute.test.service1\nservice1.threadName=main\n20:54:27.237 [main] INFO com.geniu.reactor.TestReactorOrderV2 - onErrorContinue=TestUser(name=)\n20:54:27.237 [main] INFO com.geniu.reactor.TestServiceImpl2 - execute.test.service2\nservice5.threadName=main\n20:54:28.246 [main] INFO com.geniu.reactor.TestReactorOrderV2 - onErrorContinue=TestUser(name=)\n20:54:28.246 [main] INFO com.geniu.reactor.TestServiceImpl3 - execute.test.service3\nservice6.threadName=main\nTestUser(name=name3)blockFirst \u6267\u884c\u8017\u65f6ms\uff1a2895<\/code><\/pre>\n<p>1\u3001service1 \u548c service2 \u56e0\u4e3a\u8fd4\u56de\u7a7a\uff0c\u6240\u4ee5\u7ee7\u7eed\u4e0b\u4e00\u4e2a\uff0c\u6700\u7ec8\u8fd4\u56de name3\u3002<\/p>\n<p>2\u3001\u67e5\u770b\u603b\u8017\u65f6\uff1a2895ms\u3002service1 \u8017\u65f6 500\uff0cservice2 \u8017\u65f61000\uff0cservice3 \u8017\u65f6 1000\u3002\u53d1\u73b0\u8017\u65f6\u57fa\u672c\u4e0a\u7b49\u4e8e service1 + service2 + service3 \u3002\u8fd9\u662f\u600e\u4e48\u56de\u4e8b\u5462\uff1f\u67e5\u770b\u8fd4\u56de\u6267\u884c\u7684\u7ebf\u7a0b\uff0c\u90fd\u662f main\u3002<\/p>\n<p>\u603b\u7ed3\uff1a\u8fd9\u6837\u5b9e\u73b0\u6309\u7167\u987a\u5e8f\u8fd4\u56de\u7b2c\u4e00\u4e2a\u6b63\u5e38\u6570\u636e\u3002\u4f46\u662f\u6267\u884c\u5e76\u6ca1\u6709\u5f02\u6b65\u3002\u4e0b\u4e00\u6b65\uff1a\u5982\u4f55\u5b9e\u73b0\u5f02\u6b65\u5462\uff1f<\/p>\n<h2>4 \u5b9e\u73b0\u5f02\u6b65<\/h2>\n<h3>4.1 subcribeOn \u5b9e\u73b0\u5f02\u6b65<\/h3>\n<p>\u4fee\u6539 service \u5b9e\u73b0\u3002\u589e\u52a0 <code>.subscribeOn(Schedulers.boundedElastic())<\/code><\/p>\n<p>\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"java\">@Slf4j\npublic class TestServiceImpl1 implements TestServiceI {\n    @Override\n    public Mono request() {\n        log.info(&quot;execute.test.service1&quot;);\n        return Mono.fromSupplier(() -&gt; {\n                    try {\n                        System.out.println(&quot;service1.threadName=&quot; + Thread.currentThread().getName());\n                        Thread.sleep(500);\n                    } catch (InterruptedException e) {\n                        throw new RuntimeException(e);\n                    }\n                    return &quot;&quot;;\n                })\n                \/\/\u589e\u52a0subscribeOn\n                .subscribeOn(Schedulers.boundedElastic())\n                .map(name -&gt; {\n                    return new TestUser(name);\n                });\n    }\n}<\/code><\/pre>\n<p>\u518d\u6b21\u6267\u884c\u8f93\u51fa\u5982\u4e0b\uff1a<\/p>\n<pre><code>21:02:04.213 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework\n21:02:04.265 [main] INFO com.geniu.reactor.TestServiceImpl1 - execute.test.service1\nservice4.threadName=boundedElastic-1\n21:02:04.300 [main] INFO com.geniu.reactor.TestServiceImpl2 - execute.test.service2\n21:02:04.302 [main] INFO com.geniu.reactor.TestServiceImpl3 - execute.test.service3\nservice2.threadName=boundedElastic-2\nservice3.threadName=boundedElastic-3\n21:02:04.987 [boundedElastic-1] INFO com.geniu.reactor.TestReactorOrderV2 - onErrorContinue=TestUser(name=)\n21:02:05.307 [boundedElastic-2] INFO com.geniu.reactor.TestReactorOrderV2 - onErrorContinue=TestUser(name=)\nTestUser(name=name6)blockFirst \u6267\u884c\u8017\u65f6ms\uff1a1242<\/code><\/pre>\n<p>1\u3001\u53d1\u73b0\u5177\u4f53\u5b9e\u73b0 sleep \u7684\u7ebf\u7a0b\u90fd\u4e0d\u662f main \u7ebf\u7a0b\uff0c\u800c\u662f <code>boundedElastic<\/code>\uff1b<\/p>\n<p>2\u3001\u6700\u7ec8\u6267\u884c\u8017\u65f6 1242ms\uff0c\u53ea\u6bd4\u6267\u884c\u65f6\u95f4\u6700\u957f\u7684 service2 \u548c service3 \u8017\u65f6 1000ms\uff0c\u591a\u4e00\u4e9b\u3002\u8bc1\u660e\u662f\u5f02\u6b65\u4e86\u3002<\/p>\n<h3>4.2 CompletableFuture \u5b9e\u73b0\u5f02\u6b65<\/h3>\n<p>\u4fee\u6539 service \u5b9e\u73b0\uff0c\u4f7f\u7528 CompletableFuture \u6267\u884c\u8017\u65f6\u64cd\u4f5c\uff08\u8fd9\u91cc\u662fsleep\uff0c\u5177\u4f53\u5230\u9879\u76ee\u4e2d\u53ef\u80fd\u662f\u5916\u90e8\u63a5\u53e3\u8c03\u7528\uff0cDB \u64cd\u4f5c\u7b49\uff09\uff1b\u7136\u540e\u4f7f\u7528 Mono.fromFuture \u8fd4\u56de Mono \u5bf9\u8c61\u3002<\/p>\n<pre><code class=\"java\">@Slf4j\npublic class TestServiceImpl1 implements TestServiceI{\n    @Override\n    public Mono request() {\n        log.info(&quot;execute.test.service1&quot;);\n        CompletableFuture&lt;String&gt; uCompletableFuture = CompletableFuture.supplyAsync(() -&gt; {\n            try {\n                System.out.println(&quot;service1.threadName=&quot; + Thread.currentThread().getName());\n                Thread.sleep(500);\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            return &quot;testname1&quot;;\n        });\n\n        return Mono.fromFuture(uCompletableFuture).map(name -&gt; {\n            return new TestUser(name);\n        });\n    }\n}<\/code><\/pre>\n<p>\u6267\u884c\u8fd4\u56de\u5982\u4e0b\uff1a<\/p>\n<pre><code>21:09:59.465 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework\n21:09:59.510 [main] INFO com.geniu.reactor.TestServiceImpl2 - execute.test.service2\nservice2.threadName=ForkJoinPool.commonPool-worker-1\n21:09:59.526 [main] INFO com.geniu.reactor.TestServiceImpl3 - execute.test.service3\nservice3.threadName=ForkJoinPool.commonPool-worker-2\n21:09:59.526 [main] INFO com.geniu.reactor.TestServiceImpl1 - execute.test.service1 \nservice1.threadName=ForkJoinPool.commonPool-worker-3\n21:10:00.526 [ForkJoinPool.commonPool-worker-1] INFO com.geniu.reactor.TestReactorOrder - onErrorContinue=TestUser(name=)\n21:10:00.538 [ForkJoinPool.commonPool-worker-2] INFO com.geniu.reactor.TestReactorOrder - onErrorContinue=TestUser(name=)\nTestUser(name=testname1)blockFirst \u6267\u884c\u8017\u65f6ms\uff1a1238<\/code><\/pre>\n<p>1\u3001\u8017\u65f6\u64cd\u4f5c\u90fd\u662f\u4f7f\u7528 ForkJoinPool \u7ebf\u7a0b\u6c60\u4e2d\u7684\u7ebf\u7a0b\u6267\u884c\u3002<\/p>\n<p>2\u3001\u6700\u7ec8\u8017\u65f6\u548c\u65b9\u6cd51\u57fa\u672c\u5dee\u4e0d\u591a\u3002<\/p>\n<p>\u5927\u5bb6\u90fd\u53bb\u8bd5\u8bd5\u5427~<\/p>\n<p>\u76f8\u5173\u94fe\u63a5\uff1a<\/p>\n<p><a href=\"https:\/\/link.segmentfault.com\/?enc=ETSsCL6A7ocTLSIV0r7XsA%3D%3D.JZIt0OyuyPlWsg7VH9US%2Bzpb3JgDTxqSjKOz0%2F%2BudNNQA6%2Bpk4qPdh8MSzNJQLlHaCXO3l7qgmus4wT9BQAX4SMclW30THmRatRNFwX3b3iBCklVUzeeJibACdIIXSWz\" rel=\"nofollow\">Reactor \u4e4b onErrorContinue \u548c onErrorResume<\/a><\/p>\n<p><a href=\"https:\/\/link.segmentfault.com\/?enc=OYb%2BjrjrCBiSUEj2%2BNG1Yw%3D%3D.17hHaibstR3SRu%2FnghKedXjnKguPfhhavkkkuEtAJDpfWJB2TuFiIAL1%2FgAY%2FuuSLkREGH5InF%2FVvbYPFekFagAHDW3dEPmBPOdKgsuouKhfR5e3lyPJ1WcvWVaJFpY%2F\" rel=\"nofollow\">Reactor \u4e4b flatMap vs map \u8be6\u89e3<\/a><\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042368568\">https:\/\/segmentfault.com\/a\/1190000042368568<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1 \u573a\u666f \u8c03\u7528\u591a\u4e2a\u5e73\u7ea7\u670d\u52a1\uff0c\u6309\u7167\u670d\u52a1\u4f18\u5148\u7ea7\u8fd4\u56de\u7b2c\u4e00\u4e2a\u6709\u6548\u6570\u636e\u3002 \u5177\u4f53case\uff1a\u4e00\u4e2a\u9875\u9762\u53ef\u80fd\u6709\u5f88\u591a\u7684\u5f39\u7a97\uff0c\u5f39\u7a97\u4e4b [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006308","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006308","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006308"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006308\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006308"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006308"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006308"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}