我有必须并行处理的对象流(它是长时间运行的任务),但同时我必须保留结果序列。我试图使用RxJava,但找不到任何好的解决方案。
基本思想,就是将每个对象转化为未来的功能然后按顺序调用每个未来。如果将来完成Exception,我需要重试它,直到它实际上已成功完成。
public class RxTest {
private static CompletableFuture<String> futureFunction(int i) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ThreadLocalRandom.current().nextInt(1, 100) < 10) {
throw new RuntimeException("failed.. sorry");
}
return Thread.currentThread().getName() + " " + String.valueOf(i);
});
}
public static void main(String[] args) throws InterruptedException {
Observable.range(1, 100)
.flatMap(i ->
Observable.just(i).map(RxTest::futureFunction).flatMap(Observable::from).retry()
)
.observeOn(Schedulers.from(Executors.newSingleThreadExecutor()))
.subscribe(Subscribers.create((x) -> {
System.out.println(Thread.currentThread().getName() + " " + x);
}));
}
}
在这个例子中,我收到顺序输出
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 1
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 2
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 3
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 4
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 5
pool-1-thread-1 ForkJoinPool.commonPool-worker-9 6
但每个未来都是在前一个完成之后创建和调用的,而不是像我预期的那样并行。
我正在玩observeOn()
和subscribeOn()
,没有任何效果。
答案 0 :(得分:1)
您可以使用concatMapEager
或concatEager
运行来源,但在发出时保留项目顺序:
Observable.range(1, 100)
.concatMapEager(v ->
Observable.fromCallable(() -> { ... })
.subscribeOn(Schedulers.computation())
.retry()
)
.subscribe(...)