Multithreading rx java在多个不同线程上运行可观察到

Multithreading rx java在多个不同线程上运行可观察到,multithreading,asynchronous,rx-java,Multithreading,Asynchronous,Rx Java,我是RXJava新手,所以我可能缺少一些非常基本的东西。在下面的代码示例中,我希望发生的是: SampleController在http nio线程上接收请求 CompositeService处理在新线程a上运行,并释放nio请求线程 CompositeService调用HelloService,HelloService在线程B上进行网络调用 CompositeService调用WorldService,后者在线程C上进行网络调用 3和4同时运行,当结果就绪时,我们使用结果对线程a进行网络调用

我是RXJava新手,所以我可能缺少一些非常基本的东西。在下面的代码示例中,我希望发生的是:

  • SampleController在http nio线程上接收请求

  • CompositeService处理在新线程a上运行,并释放nio请求线程

  • CompositeService调用HelloService,HelloService在线程B上进行网络调用

  • CompositeService调用WorldService,后者在线程C上进行网络调用

  • 3和4同时运行,当结果就绪时,我们使用结果对线程a进行网络调用

    相反,我看到的是3和4在http nio线程上顺序执行,只有CompositeService在新线程上执行。我在3和4中的subscribeOn调用似乎没有任何效果。如何使3和4同时运行

    采样控制器

    @RestController
    @RequestMapping("/rx-java-sample")
    public class SampleController {
    
        private static Logger log = LoggerFactory.getLogger(SampleController.class);
    
        @Autowired
        private CompositeService compositeService;
    
        @RequestMapping(method = RequestMethod.GET, 
            produces = { MediaType.APPLICATION_JSON_VALUE })
        public DeferredResult<String> getCompositeString() 
                        throws ApiGatewayException, ApiValidationException {
            log.info("Received getCompositeObject request");
    
            Observable<String> compositeObject = compositeService.getCompositeString();
    
            return toDeferredResult(compositeObject);
        }
    
        private DeferredResult<String> toDeferredResult(Observable<String> compositeObject) {
            DeferredResult<String> result = new DeferredResult<String>();
    
            compositeObject.subscribeOn(Schedulers.newThread()).subscribe(new Observer<String>() {
                @Override
                public void onCompleted() {
                }
    
                @Override
                public void onError(Throwable throwable) {
                    result.setErrorResult(throwable);
                }
    
                @Override
                public void onNext(String compositeString) {
                    log.info("Returning compositeObject: " + compositeString);
                    result.setResult(compositeString);
                }
            });
    
            return result;
        }
    }
    
    @Service
    public class HelloService {
    
        private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getHello() {
            log.trace("calling get hello");
            return Observable.just(makeNetworkCall());
        }
    
        private String makeNetworkCall() {
            log.trace("making hello network call");
            return "hello";
        }
    }
    

    问题似乎是我使用了Observable.just而不是Observable.fromCallable。从上面如下修改服务代码产生了我想要的行为。我仍然在寻找反馈,看这是否是“推荐”的方法。特别是,我不确定在CompositeService中使用Toblock()是否正确。我可能会在我的代码中广泛使用这种模式,我希望它正确

    HelloService

    @Service
    public class WorldService {
    
    private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getWorld() {
            log.trace("calling get world");
            return Observable.just(makeNetworkCall());
        }
    
        private String makeNetworkCall() {
            log.trace("making world network call");
            return "world";
        }
    }
    
    @Service
    public class CompositeService {
    
        private Logger log = LoggerFactory.getLogger(CompositeService.class);
    
        @Autowired
        private HelloService helloService;
    
        @Autowired
        private WorldService worldService;
    
        public Observable<String> getCompositeString() {
            log.trace("Calling getCompositeObject");
    
            Observable<String> foo = helloService.getHello().subscribeOn(Schedulers.newThread());
            Observable<String> bar = worldService.getWorld().subscribeOn(Schedulers.newThread());
    
            return Observable.zip(foo, bar, (f, b) -> makeNetworkCall(f,b));
        }
    
        private String makeNetworkCall(String hello, String world) {
            log.trace("making composite network call");
            return hello + " " +  world;
        }
    }
    
    2016-06-16 07:10:13 INFO [http-nio-9050-exec-1] [SampleController.java:32] Received getCompositeObject request
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [CompositeService.java:23] Calling getCompositeObject
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [HelloService.java:15] calling get hello
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [HelloService.java:20] making hello network call
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [WorldService.java:15] calling get world
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [WorldService.java:20] making world network call
    2016-06-16 07:10:13 TRACE [RxNewThreadScheduler-3] [CompositeService.java:32] making composite network call
    2016-06-16 07:10:13 INFO [RxNewThreadScheduler-3] [SampleController.java:54] Returning compositeObject: hello world
    
    @Service
    public class HelloService {
    
        private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getHello() {
            log.trace("calling get hello");
    
            return Observable.fromCallable(() -> { 
                return makeNetworkCall();
            });
        }
    
        private String makeNetworkCall() {
            log.trace("making hello network call");
            return "hello";
        }
    }
    
    @Service
    public class WorldService {
    
    private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getWorld() {
            log.trace("calling get world");
    
            return Observable.fromCallable(() -> { 
                return makeNetworkCall();
            });
        }
    
        private String makeNetworkCall() {
            log.trace("making world network call");
            return "world";
        }
    }
    
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [CompositeService.java:29] Calling getCompositeObject
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [HelloService.java:15] calling get hello
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [WorldService.java:15] calling get world
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-2] [HelloService.java:23] making hello network call
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-3] [WorldService.java:23] making world network call
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-3] [CompositeService.java:38] making composite network call
    2016-06-16 08:15:50 INFO [RxNewThreadScheduler-1] [SampleController.java:54] Returning compositeObject: hello world
    
    日志

    @Service
    public class WorldService {
    
    private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getWorld() {
            log.trace("calling get world");
            return Observable.just(makeNetworkCall());
        }
    
        private String makeNetworkCall() {
            log.trace("making world network call");
            return "world";
        }
    }
    
    @Service
    public class CompositeService {
    
        private Logger log = LoggerFactory.getLogger(CompositeService.class);
    
        @Autowired
        private HelloService helloService;
    
        @Autowired
        private WorldService worldService;
    
        public Observable<String> getCompositeString() {
            log.trace("Calling getCompositeObject");
    
            Observable<String> foo = helloService.getHello().subscribeOn(Schedulers.newThread());
            Observable<String> bar = worldService.getWorld().subscribeOn(Schedulers.newThread());
    
            return Observable.zip(foo, bar, (f, b) -> makeNetworkCall(f,b));
        }
    
        private String makeNetworkCall(String hello, String world) {
            log.trace("making composite network call");
            return hello + " " +  world;
        }
    }
    
    2016-06-16 07:10:13 INFO [http-nio-9050-exec-1] [SampleController.java:32] Received getCompositeObject request
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [CompositeService.java:23] Calling getCompositeObject
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [HelloService.java:15] calling get hello
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [HelloService.java:20] making hello network call
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [WorldService.java:15] calling get world
    2016-06-16 07:10:13 TRACE [http-nio-9050-exec-1] [WorldService.java:20] making world network call
    2016-06-16 07:10:13 TRACE [RxNewThreadScheduler-3] [CompositeService.java:32] making composite network call
    2016-06-16 07:10:13 INFO [RxNewThreadScheduler-3] [SampleController.java:54] Returning compositeObject: hello world
    
    @Service
    public class HelloService {
    
        private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getHello() {
            log.trace("calling get hello");
    
            return Observable.fromCallable(() -> { 
                return makeNetworkCall();
            });
        }
    
        private String makeNetworkCall() {
            log.trace("making hello network call");
            return "hello";
        }
    }
    
    @Service
    public class WorldService {
    
    private Logger log = LoggerFactory.getLogger(HelloService.class);
    
        public Observable<String> getWorld() {
            log.trace("calling get world");
    
            return Observable.fromCallable(() -> { 
                return makeNetworkCall();
            });
        }
    
        private String makeNetworkCall() {
            log.trace("making world network call");
            return "world";
        }
    }
    
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [CompositeService.java:29] Calling getCompositeObject
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [HelloService.java:15] calling get hello
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-1] [WorldService.java:15] calling get world
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-2] [HelloService.java:23] making hello network call
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-3] [WorldService.java:23] making world network call
    2016-06-16 08:15:50 TRACE [RxNewThreadScheduler-3] [CompositeService.java:38] making composite network call
    2016-06-16 08:15:50 INFO [RxNewThreadScheduler-1] [SampleController.java:54] Returning compositeObject: hello world
    

    您希望对以下情况使用
    Observable::defer

      public Observable<String> getWorld() {
          log.trace("calling get world");
    
          return Observable.defer(() -> makeNetworkCall());
      }
    
    publicobservable getWorld(){
    trace(“调用get world”);
    return Observable.defer(()->makeNetworkCall());
    }
    
    这确保了每次在可观察对象上进行重写时都会调用代码


    另外,我建议使用
    Schedulers.io()
    ;它是一个可配置的线程池,默认情况下可根据需要扩展。

    fyi,cpu绑定的工作有Schedulers.computation(),io绑定的工作有Schedulers.io(),通常比Schedulers.newThread()更好。