我正在寻找一种方法将多个订阅者附加到RxJava Observable流,每个订阅者异步处理发出的事件。
我首先尝试使用.flatMap(),但这似乎并不适用于任何后续订阅者。所有订阅者都在同一个线程上处理事件。
.flatMap(s -> Observable.just(s).subscribeOn(Schedulers.newThread()))
最终工作的是通过每次创建一个新的Observable来消耗新线程中的每个事件:
Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
.subscribe(j -> {
Observable.just(j)
.subscribeOn(Schedulers.newThread())
.subscribe(i -> {
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
});
});
输出:
s1=>RxNewThreadScheduler-1=>1
s1=>RxNewThreadScheduler-2=>2
s1=>RxNewThreadScheduler-3=>3
最终结果是多个订阅者:
ConnectableObservable<String> e = Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
.publish();
e.subscribe(j -> {
Observable.just(j)
.subscribeOn(Schedulers.newThread())
.subscribe(i -> {
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
});
});
e.subscribe(j -> {
Observable.just(j)
.subscribeOn(Schedulers.newThread())
.subscribe(i -> {
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("s2=>" + Thread.currentThread().getName() + "=>" + i);
});
});
e.connect();
输出:
s2=>RxNewThreadScheduler-4=>2
s1=>RxNewThreadScheduler-1=>1
s1=>RxNewThreadScheduler-3=>2
s2=>RxNewThreadScheduler-6=>3
s2=>RxNewThreadScheduler-2=>1
s1=>RxNewThreadScheduler-5=>3
然而,这看起来有点笨重。是否有一个更优雅的解决方案或者RxJava不是一个很好的用例呢?
答案 0 :(得分:0)
使用.flatMap(s -> Observable.just(s).observeOn(Schedulers.newThread())....)
答案 1 :(得分:0)
如果我正确地理解了rx-contract,那么你正试图做一些与之相反的事情。
让我们看一下合约
RxJava Observable的合约是事件(onNext(),onCompleted(),onEr ror())永远不会同时发出。换句话说,一个Observable stream必须始终序列化并且是线程安全的。每个事件都可以从a发出 不同的线程,只要排放不并发。这意味着没有 inter- 离开或同时执行onNext()。如果仍在执行onNext() 一个线程,另一个线程无法再次开始调用它(交错)。 --Tomasz Nurkiewicz在Reactive Programming with RxJava
在我看来,您试图通过在外部订阅中使用嵌套订阅来破解合同。对订阅者的onNext调用不再被序列化。
为什么不将&#34; async&#34; -workload从订阅者移动到flatMap-operator并订阅新的observable:
ConnectableObservable<String> stringObservable = Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
.flatMap(s -> {
return Observable.just(s).subscribeOn(Schedulers.computation());
})
.publish();
stringObservable
.flatMap(s -> {
// do More asyncStuff depending on subscription
return Observable.just(s).subscribeOn(Schedulers.newThread());
})
.subscribe(s -> {
// use result here
});
stringObservable
.subscribe(s -> {
// use immediate result here.
});
stringObservable.connect();
答案 2 :(得分:0)
flatMap
内的doOnNext
上的Observable
以及flatMap
将产生与您相同的输出。
onNext()
始终以顺序方式调用,因此在doOnNext
之后使用flatMap
也不会对您有用。由于同样的原因,在最终的subscribe
中写入操作在您的情况下不起作用。
以下代码是使用RxJava2编写的。在RxJava的第1版中,您必须在try-catch
周围添加Thread.sleep
块。
ConnectableObservable<String> e = Observable.just("1", "2", "3").publish();
e.flatMap(
s -> Observable.just(s)
.subscribeOn(Schedulers.newThread())
.doOnNext(i -> { // <<<<<<
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
}))
.subscribe();
e.flatMap(
s -> Observable.just(s)
.subscribeOn(Schedulers.newThread())
.doOnNext(i -> { // <<<<<<
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
System.out.println("s2=>" + Thread.currentThread().getName() + "=>" + i);
}))
.subscribe();
e.connect();
答案 3 :(得分:0)
您可以使用Flowable和parallel实现它
Flowable.fromIterable(Arrays.asList("1", "2", "3"))
.parallel(3)
.runOn(Schedulers.newThread())
.map(item -> {
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + item);
return Completable.complete();
})
.sequential().subscribe();