使用rx实体时,我有以下方案:
Observerable1
|
------------------
| | |
S1(*) S2(*) S3 (onCompleted() starts another observable)
|
Observable2
|
S4(*)
我需要知道*
的所有订阅者何时完成工作(S1,S2,S4
)。由于它们可以在不同的线程中执行,我需要一些同步机制,或者rx-java
有一些开箱即用的解决方案?
用于说明当前设计的一些示例代码:
@Component
public class BatchReader {
@Autowired List<Subscriber<List<Integer>>> subscribers;
public void start() {
ConnectableObservable<List<Integer>> observable1 = createObservable();
subscribers.forEach(observable1::subscribe);
observable1.connect();
}
private ConnectableObservable<List<Integer>> createObservable() {
return Observable.create((Subscriber<? super List<Integer>> subscriber) -> {
try {
subscriber.onStart();
while (someCondition) {
List<Integer> numbers = ...;
subscriber.onNext(numbers);
}
subscriber.onCompleted();
} catch (Exception ex) {
subscriber.onError(ex);
}
}).observeOn(Schedulers.newThread()).publish();
}
}
在S3中,我有以下逻辑:
@Component
public class S3 extends Subscriber<List<Integer>> {
@Autowired AnotherBatchReader anotherBatchReader;
....
@Override
public void onCompleted() {
anotherBatchReader.start();
}
...
}
S4订阅了AnotherBatchReader:
@Component
public class AnotherBatchReader {
@Autowired S4<List<Foo>> subscriber4;
public void start() {
Observable<List<Foo>> observable2 = createObservable();
observable2.subscribe(subscriber4);
}
private Observable<List<Foo>> createObservable() {
return Observable.create(subscriber -> {
try {
subscriber.onStart();
while (someConditionBar) {
List<Foo> foo = ...;
subscriber.onNext(foo);
}
subscriber.onCompleted();
}
} catch (RuntimeException ex) {
subscriber.onError(ex);
}
});
}
}
当我感兴趣的所有订阅者都有兴趣完成他们的工作时,有没有办法得到适当的通知? rx支持它吗?或者也许有更好的设计可以支持它?
修改
我有单独的订阅者,因为每个订阅者都有不同的行为。最后,*
(S1,S2,S3)的订阅者将其数据写入xml文件。但是
onNext()
中的数据,做一些工作,并将结果直接写入文件onNext()
中的数据,做一些工作,在字段中累积结果,然后用onCompleted
onNext
中的数据,做一些工作,将结果写入DB并在调用onCompleted
后启动另一个observable,它开始从db获取数据并将其推送到S4 onNext()
中的数据,做一些工作并写入文件我需要在S3中将数据写入数据库的原因是因为onNext()
中接收到的数据生成的结果必须是唯一的,但是我正在从{{{{}}批量获取数据1}}我无法保证这种独特性,所以DB会照顾它。
当然在Observable1
中,我不能像在S3
中那样做(将所有结果累积在内存中),因为S3中存在的结果的乘法与S2。
答案 0 :(得分:1)
感谢您的澄清。在我看来,明智地应用现有的运营商将最大限度地减少您的代码。现在,我没有所有细节,但你所做的事情感觉很像这样:
Observable<T> observable1 = ...
.share();
Observable<?> S1 = S1(observable1);
Observable<?> S2 = S2(observable1);
Observable<?> S3 = S3(observable1);
Observable<?> S4 = defer(() -> readFromDatabase()).compose(S4::generate);
Observable.merge(S1,S2,S3.ignoreElements().switchIfEmpty(S4))
.ignoreElements()
.onComplete(...)
.subscribe();
当然,细节会有所不同,具体取决于原始观察结果是热还是冷,以及S[1-4]
的详细信息。
另外,不要试图自己开车Subscribers
,让框架为你做这件事,你会从中获得更多 - f.e。:
S4 = Observable.create(SyncOnSubscribe.generateStateless(
observer -> observer.onNext(<get List<Foo>>)
))
.takeWhile(list -> someConditionBar);
编辑:这是XY问题的一个案例 - 我们都经历过......