RxJava:PublishSubject同步执行

时间:2018-07-03 17:47:28

标签: java rx-java publish-subscribe

我需要一种功能,该功能允许异步将消息推送到我的PublishSubject并通过ConnectableObservable以一定的速度(实际上是一个一个地)处理它们。不幸的是,似乎onNext中对PublishSubject的调用直到基础Subscriber处理该消息后才释放。

处理每条消息要花好几秒钟的时间,在调试模式下,我发现它在调用将消息推送到PublishSubject的方法从堆栈中删除之前已执行-"After push..."始终在内部日志内部之后出现在控制台中Subscriber ...

所以我有这个RestEndpoint:

@PUT
@Path("{id}")
@TokenAuthenticated
public Response postResource(@PathParam(value="id") final String extId) {
    executorService.execute(new Runnable() {

        @Override
        public void run() {
            try {
                Message metadata = processor.apply(extId);
                log.info("Before push...");
                dataImporter.pushData(metadata);
                log.info("After push...");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    return Response.ok("Request received successfully").build();

}

这是DataImporter的构造函数:

public DataImporter(final String configFile) {
        dataToImportSubject = PublishSubject.create();
        dataToImportObservable = dataToImportSubject.publish();
        dataToImportObservable.connect();
        dataToImportObservable
            .onBackpressureBuffer(1, new Action0() {

                @Override
                public void call() {
                    logger.debug("Buffer full...");
                }
            })
            .subscribeOn(Schedulers.io())
            .subscribe(new Subscriber<Message>() {

                @Override
                public void onCompleted() {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onError(Throwable e) {
                    logger.error("Error importing "+e.getMessage());
                }

                @Override
                public void onNext(Message value) {
                    request(1);
                    importResult(configFile, value);
                }

                @Override
                public void onStart() {
                    request(1);
                }
            });
    }

然后,DataImporter的pushData只是推向PublishSubject的{​​{1}}方法。.:

onNext

这是public void pushData(Message metadata) { dataToImportSubject.onNext(metadata); } PublishSubject的声明:

ConnectableObservable

2 个答案:

答案 0 :(得分:2)

PublishSubject在原始onXXX调用的线程上发出给其使用者:

JavaDocs

  

计划程序

     

PublishSubject在特定的Scheduler上默认不运行,并且Observer会在线程中收到有关分别调用onXXX方法的通知。

您必须使用observeOn将处理移至其他线程,因为observeOn可以将onXXX调用移至另一个线程。

subscribeOn通常不会对Subject产生任何实际影响,因为它只会影响订阅线程,并且不会调制对这些主题的后续onXXX调用。

答案 1 :(得分:0)

默认情况下,RxJava是同步的。您需要在观察者链中引入运算符,以对其他线程执行操作。当您阅读Observable中每个运算符的文档时,将看到诸如“ ...在特定调度程序上没有运算符”之类的语句-这表明数据同步流过该运算符。

要使观察者链在其他线程上执行操作,可以将subscribeOn()之类的运算符与调度程序一起使用,以对该调度程序执行操作。在您的示例中,您可能希望使用Schedulers.io()提供后台线程。