对Observable发出的每个项目执行不同的并行操作

时间:2014-08-22 20:41:57

标签: rx-java

考虑以下示例

        Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> integerSubscriber) {
                for (int i = 1; i <= 10; i++) {
                    integerSubscriber.onNext(i);

                }
                integerSubscriber.onCompleted();
            }
        }).parallel(new Func1<Observable<Integer>, Observable<Result>>() {

            @Override
            public Observable<Result> call(Observable<Integer> integerObservable) {
               return integerObservable.flatMap(new Func1<Integer, Observable<Result>>() {

                   @Override
                   public Observable<Result> call(final Integer i) {
                       Result r = new Result();

                       r.i = i;
                       r.iSquare = i * i;
                       r.iQube = i * i * i;

                       return Observable.just(r);
                   }

               });
            }
        }).subscribe(new Observer<Result> () {

            @Override
            public void onCompleted() {
                System.out.println("Done.");
            }

            @Override
            public void onError(Throwable t) {
                t.printStackTrace();
            }

            @Override
            public void onNext(Result r) {
                System.out.println(r.i + ", " + r.iSquare + ", " + r.iQube);
            }

        });

这将采用并行线程上的每个整数来评估它的平方和立方体。但是,平方和立方体的过程是一个接一个地完成并由同一个线程完成的。在平行螺纹上进行平方和立方的最佳方法是什么?

所以当前

的代码部分
@Override
public Observable<Result> call(Observable<Integer> integerObservable) {
   return integerObservable.flatMap(new Func1<Integer, Observable<Result>>() {

       @Override
       public Observable<Result> call(final Integer i) {
           Result r = new Result();

           r.i = i;
           r.iSquare = i * i;
           r.iQube = i * i * i;

           return Observable.just(r);
       }

   });
}

会变成

public Observable<Result> call(Observable<Integer> integerObservable) {
   return integerObservable.flatMap(new Func1<Integer, Observable<Result>>() {



                   @Override
                   public Observable<Result> call(final Integer i) {
                       Result r = new Result();

                       r.i = i;
                       r.iSquare = doOnParallelThread(i * i);
                       r.iQube = doOnParallelThread(i * i * i);



                       return Observable.just(r);
                   }

               });
        }

2 个答案:

答案 0 :(得分:0)

我根据下面的kjones解决方案提出了一个可能的解决方案。

final List<Result> results = new ArrayList<>();

Observable.create(new Observable.OnSubscribe<Integer>() {

    @Override
    public void call(Subscriber<? super Integer> integerSubscriber) {
        for (int i = 1; i <= 10; i++) {
            integerSubscriber.onNext(i);

        }
        integerSubscriber.onCompleted();
    }
})
.parallel(new Func1<Observable<Integer>, Observable<Result>>() {

    @Override
    public Observable<Result> call(Observable<Integer> integerObservable) {
        return integerObservable.flatMap(new Func1<Integer, Observable<Result>>() {

            @Override
            public Observable<Result> call(Integer i) {
                System.out.println(Thread.currentThread().getName() + " processing " + i);
                return Observable.zip(
                        Observable.just(i),
                        Observable.just(i)
                                .map(new Func1<Integer, Integer> () {

                                      @Override
                                      public Integer call(Integer i) {
                                          System.out.println(Thread.currentThread().getName() + " squaring " + i);
                                          sleep();
                                          return i * i;
                                      }
                                })
                                .subscribeOn(Schedulers.computation()),
                        Observable.just(i)
                                .map(new Func1<Integer, Integer> () {

                                      @Override
                                      public Integer call(Integer i) {
                                          System.out.println(Thread.currentThread().getName() + " qubing " + i);
                                          sleep();
                                          return i * i * i;
                                      }

                                })
                                .subscribeOn(Schedulers.computation()),
                        Observable.just(i)
                                .map(new Func1<Integer, Integer> () {

                                      @Override
                                      public Integer call(Integer i) {
                                          System.out.println(Thread.currentThread().getName() + " 4th power " + i);
                                          sleep();
                                          return i * i * i * i;
                                      }

                                })
                                .subscribeOn(Schedulers.computation()),
                        new Func4<Integer, Integer, Integer, Integer, Result> () {

                            @Override
                            public Result call(Integer i, Integer square, Integer qube, Integer fourth) {
                                System.out.println(Thread.currentThread().getName() + " combining results " + i + ", " + square + ", " + qube + ", " + fourth);
                                return new Result(i,  square, qube, fourth);
                            }

                        });
            }

        });
    }

})
.subscribe(new Observer<Result>() {

    @Override
    public void onCompleted() {
        System.out.println(Thread.currentThread().getName() + " computed " + results);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onNext(Result r) {
        results.add(r);
    }

});

有更好的方法吗?

答案 1 :(得分:0)

Observable
        .range(1, 10)
        .parallel(new Func1<Observable<Integer>, Observable<Result>>() {
            @Override
            public Observable<Result> call(Observable<Integer> parallelIntegerObservable) {
                final Observable<Integer> integerObservable =
                        parallelIntegerObservable
                                .cache();

                // Zip runs in parallel but subscribes serially to each subscriber. Use
                // the subscribeOn() method to force each calculation to run async. If
                // iSquare & iQube were long running or blocking operations then there
                // is probably no need to use the subscribeOn() method call below.
                return Observable.zip(
                        integerObservable,
                        integerObservable
                                .map(new Func1<Integer, Integer>() {
                                    @Override
                                    public Integer call(Integer i) {
                                        return i * i;
                                    }
                                }),
                        integerObservable
                                .map(new Func1<Integer, Integer>() {
                                    @Override
                                    public Integer call(Integer i) {
                                        return i * i * i;
                                    }
                                }),
                        new Func3<Integer, Integer, Integer, Result>() {
                            @Override
                            public Result call(Integer i, Integer iSquare, Integer iQube) {
                                return new Result(i, iSquare, iQube);
                            }
                        }
                );
            }
        })
        .subscribeOn(Schedulers.computation())
        .subscribe(
                // Your same logic here.
        );

编辑: .parallel运算符创建的integerObservable似乎只能订阅一次(RxJava 0.20.0)。我修改了上面的代码来缓存该observable发出的整数,以便它只有一个订阅者。以下代码是修改后的代码:

public Observable<Result> call(Observable<Integer> parallelIntegerObservable) {
    final Observable<Integer> integerObservable =
            parallelIntegerObservable
                    .cache();