是否可以在" unscription"之后在rxJava中运行后台操作?
Ex:我创建了一个由3个字符串组成的流:A,B,C和I为C引入了高延迟,并为A和B引入了相同的延迟。通过使用运算符first()我取消订阅速度太快C和C没有时间被执行所以取消描述杀死C.是否有一种简单的方法让C继续在后台运行???
@Test
public void test_69_b() throws Exception {
List<String> intList = Arrays.asList("A", "B", "C");
print("start");
Observable test = Observable.from(intList)
.flatMap(this::findWrapperS)
.first();
print("build finnished");
test.subscribe(this::printAtSub);
print("End");
Sleeper.sleep(Duration.ofSeconds(4));
}
private Observable<String> findWrapperS(String id) {
return Observable.just(id).doOnUnsubscribe(() -> {
print("Wrapper <" + id + "> is released");
})
.observeOn(Schedulers.io())
.flatMap(i -> Observable.fromCallable(() -> sendBackString(i)));
}
private String sendBackString(String string) {
switch (string){
case "C":
Sleeper.sleep(Duration.ofMillis(1000));
print("Hello " + string);
return string;
default:
Sleeper.sleep(Duration.ofMillis(10));
print("Hello " + string);
return string;
}
}
Given logs
=================
18:19:47.806 [Test worker] INFO tests.TestRunner - Got: start
18:19:47.831 [Test worker] INFO tests.TestRunner - Got: build finnished
18:19:47.989 [Test worker] INFO tests.TestRunner - Got: End
18:19:47.994 [Test worker] INFO tests.Sleeper - Sleeping PT4S ms
18:19:47.998 [RxIoScheduler-2] INFO tests.Sleeper - Sleeping PT0.01S ms
18:19:47.999 [RxIoScheduler-3] INFO tests.Sleeper - Sleeping PT0.01S ms
18:19:47.999 [RxIoScheduler-4] INFO tests.Sleeper - Sleeping PT1S ms
18:19:48.009 [RxIoScheduler-3] INFO tests.TestRunner - Got: Hello B
18:19:48.010 [RxIoScheduler-3] INFO tests.TestRunner - TERMINAL EVENT --->: B
18:19:48.012 [RxIoScheduler-3] INFO tests.TestRunner - Got: Wrapper <A> is released
18:19:48.013 [RxIoScheduler-3] INFO tests.TestRunner - Got: Wrapper <C> is released
18:19:48.015 [RxIoScheduler-3] INFO tests.TestRunner - Got: Wrapper <B> is released
18:19:48.015 [RxIoScheduler-2] INFO tests.TestRunner - Got: Hello A
18:19:48.021 [RxIoScheduler-4] WARN tests.Sleeper - Sleep interrupted
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at tests.Sleeper.sleep(Sleeper.java:24)
at tests.TestRunner.sendBackString(TestRunner.java:249)
at tests.TestRunner.lambda$null$15(TestRunner.java:242)
at rx.internal.operators.OnSubscribeFromCallable.call(OnSubscribeFromCallable.java:48)
at rx.internal.operators.OnSubscribeFromCallable.call(OnSubscribeFromCallable.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:250)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:147)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:77)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:227)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:228)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
18:19:48.023 [RxIoScheduler-4] INFO tests.TestRunner - Got: Hello C
答案 0 :(得分:1)
如果您想要完成一个长期运行的observable,最简单的方法是引入share()
运算符。它将有两个订阅者,一个用于确保进程完成的空订阅者,另一个用于获取first()
项并取消订阅的订阅者。
与往常一样,您需要关注对象的生命周期,并在资源不再可行时释放资源。
// Hold on to long running subscriptions so we can release
// them at the proper time
CompositeSubscription longRunningSubscribers = new CompositeSubscription();
...
private Observable<String> findWrapperS(String id) {
Observable<String> obs = Observable.just(id).doOnUnsubscribe(() -> {
print("Wrapper <" + id + "> is released");
})
.observeOn(Schedulers.io())
.flatMap(i -> Observable.fromCallable(() -> sendBackString(i)))
.share();
Subscription longTerm = obs
.subscribe( ignored -> {}, error -> {} );
longRunningSubscribers.add( longTerm );
return obs;
}
现在,findWrapperS()
返回一个可以订阅和取消订阅的observable,而不会停止长时间运行的操作。当操作终止时,观察者链资源将被释放。但是,您仍可能需要在处理结束时致电longRunningSubscribers.unsubscribe()
以释放订阅的资源。如果一切都已经完成,那么它所做的就是释放少量内存,这不是一件坏事。
答案 1 :(得分:0)
@BobDalgleish如果我在第一个()之前尝试“cache()”会怎么样?:
@Test public void test_69_b() throws Exception {
List<String> intList = Arrays.asList("A", "B", "C");
print("start");
Observable test = Observable.from(intList)
.flatMap(this::findWrapperS)
.cache();
.first();
print("build finnished");
test.subscribe(this::printAtSub);
print("End");
Sleeper.sleep(Duration.ofSeconds(4));
}
我觉得它与你的命题有点类似,意思是缓存保留了第二个订阅者发出的可观察序列。