RxJava - SwitchMap alike with multiple limited active streams
我想知道如何转换类似于switchMap的可观察对象,但不限于具有多个(有限)流的单个活动流。
目的是让多个任务同时工作,直到某个任务计数限制,并允许新任务以FIFO队列策略开始,这意味着到达的任何新任务将立即开始,并且队列中最旧的任务将被取消。
switchMap将为源的每次发射创建Observable流,并在创建新的Observable流时取消先前运行的Observable流,我想实现类似的功能,但允许一定级别的并发(例如flatMap),这意味着允许创建Observable的数量对于每个发射,并发运行并达到一定的并发限制,当达到并发限制时,最早的可观察对象将被取消,而新的可观察对象将开始。
实际上,这也与具有maxConcurrent的flatMap相似,但是当达到maxConcurrent时,不是新的Observable在队列中等待,而是取消较旧的Observable并立即输入新的Observable。
您可以尝试使用此变压器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static <T, R> Observable.Transformer<T, R> switchFlatMap( int n, Func1<T, Observable<R>> mapper) { return f -> Observable.defer(() -> { final AtomicInteger ingress = new AtomicInteger(); final Subject<Integer, Integer> cancel = PublishSubject.<Integer>create().toSerialized(); return f.flatMap(v -> { int id = ingress.getAndIncrement(); Observable<R> o = mapper.call(v) .takeUntil(cancel.filter(e -> e == id + n)); cancel.onNext(id); return o; }); }) ; } |
演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public static void main(String[] args) { PublishSubject<Integer> ps = PublishSubject.create(); @SuppressWarnings("unchecked") PublishSubject<Integer>[] pss = new PublishSubject[3]; for (int i = 0; i < pss.length; i++) { pss[i] = PublishSubject.create(); } AssertableSubscriber<Integer> ts = ps .compose(switchFlatMap(2, v -> pss[v])) .test(); ps.onNext(0); ps.onNext(1); pss[0].onNext(1); pss[0].onNext(2); pss[0].onNext(3); pss[1].onNext(10); pss[1].onNext(11); pss[1].onNext(12); ps.onNext(2); pss[0].onNext(4); pss[2].onNext(20); pss[2].onNext(21); pss[2].onNext(22); pss[1].onCompleted(); pss[2].onCompleted(); ps.onCompleted(); ts.assertResult(1, 2, 3, 10, 11, 12, 20, 21, 22); } |
尽管无法使用现成的解决方案,但类似下面的内容应该有所帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static void main(String[] args) { Observable.create(subscriber -> { for (int i = 0; i < 5; i++) { Observable.timer(i, TimeUnit.SECONDS).toBlocking().subscribe(); subscriber.onNext(i); } }) .switchMap( n -> { System.out.println("Main task emitted event -" + n); return Observable.interval(1, TimeUnit.SECONDS).take((int) n * 3) .doOnUnsubscribe(() -> System.out.println("Unsubscribed for main task event -"+ n)); }).subscribe(n2 -> System.out.println("\\t" + n2)); Observable.timer(20, TimeUnit.SECONDS).toBlocking().subscribe(); } |
因此,也许您的情况下,您可能有兴趣使用
下面的伪代码可能有助于更好地理解。
1 2 3 4 5 6 7 8 | getTaskObservable() .switchMap( task -> { System.out.println("Main task emitted event -" + task); return Observable.create(subscriber -> { initiateTaskAndNotify(task, subscriber); }).doOnUnsubscribe(() -> checkAndKillIfMaxConcurrentTasksReached(task)); }).subscribe(value -> System.out.println("Done with task and got output" + value)); |