考虑以下示例
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);
}
});
}
答案 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();