好吧,这是我在StackOverflow中遇到的第一个问题,但是在与RxJava
战斗了几天之后,我找不到其他解决方案,我自己尝试了很多事情,仔细研究了文档和其他文章,但是我不知道我需要做什么。我尝试了flatMap
,zip
,merge
和其他几种组合,但是总是达到死胡同,而最接近的解决方案是下面的代码。我将不胜感激。
我需要一个给定输入列表的方法,该方法使用列表的不同输入执行并行调用,并且在所有并行调用完成之前不要继续执行。还必须保留不同执行的结果以供以后使用( EDIT :在开始执行的同一线程中)。
public void parallelExecution(List<Integer> calls) {
List<String> results = new ArrayList<>();
logger.debug("Starting parallel executions");
Observable.fromIterable(calls)
.flatMap(val -> Observable.just(val).observeOn(Schedulers.io())
.doOnNext(item -> results.add(simpleAsync(item).toString())))
.subscribe(call -> logger.debug("Execution: {}", Thread.currentThread().getName()));
logger.debug("Ending parallel executions");
for (String x : results) {
logger.debug("Results: {}", x);
}
}
private Integer simpleAsync(Integer number) {
Integer result = number * number;
logger.info("Pre log {}: {}", Thread.currentThread().getName(), result);
try {
Thread.sleep(number * 500);
} catch (Exception e) {
}
logger.info("Post log {}: {}", Thread.currentThread().getName(), result);
return result;
}
问题在于此代码不会“等待”执行“ simpleAsync”方法,它会在没有“结果”日志(尚无结果)的情况下完成执行,然后是“发布日志” “跟踪显示在不同的线程中执行:
Starting parallel executions
Ending parallel executions
Pre log RxCachedThreadScheduler-1: 1
Pre log RxCachedThreadScheduler-2: 4
Pre log RxCachedThreadScheduler-3: 9
Pre log RxCachedThreadScheduler-4: 16
Pre log RxCachedThreadScheduler-5: 25
Post log RxCachedThreadScheduler-1: 1
Execution: RxCachedThreadScheduler-1
Post log RxCachedThreadScheduler-2: 4
Execution: RxCachedThreadScheduler-2
Post log RxCachedThreadScheduler-3: 9
Execution: RxCachedThreadScheduler-3
Post log RxCachedThreadScheduler-4: 16
Execution: RxCachedThreadScheduler-4
Post log RxCachedThreadScheduler-5: 25
Execution: RxCachedThreadScheduler-5
如果我删除“ observeOn”语句,则该方法等待调用完成,但是它们是顺序执行的(在同一线程中):
Starting parallel executions
Pre log Default Executor-thread-9: 1
Post log Default Executor-thread-9: 1
Execution: Default Executor-thread-9
Pre log Default Executor-thread-9: 4
Post log Default Executor-thread-9: 4
Execution: Default Executor-thread-9
Pre log Default Executor-thread-9: 9
Post log Default Executor-thread-9: 9
Execution: Default Executor-thread-9
Pre log Default Executor-thread-9: 16
Post log Default Executor-thread-9: 16
Execution: Default Executor-thread-9
Pre log Default Executor-thread-9: 25
Post log Default Executor-thread-9: 25
Execution: Default Executor-thread-9
Ending parallel executions
Results: 1
Results: 4
Results: 9
Results: 16
Results: 25
答案 0 :(得分:0)
您是否尝试过使用zip?
public void parallelExecution(List<Integer> calls) {
logger.debug("Starting parallel executions");
// Create an iterable observables
List<Observable<Integer>> observables = calls.stream()
.map(i -> {
return Observable.fromCallable(() -> simpleAsync(i))
.subscribeOn(Schedulers.newThread());
})
.collect(Collectors.toList());
Observable.zip(observables, objects -> { // Zip observables
return Arrays.stream(objects)
.map(Object::toString)
.collect(Collectors.toList());
})
.doOnNext(results -> logger.debug("Ending parallel executions"))
.subscribe(results -> { // Subscribe to the result.
// Put your code that needs to "wait"
for (String x : results) {
logger.debug("Results: {}", x);
}
});
}
结果将如下所示:
Starting parallel executions
Pre log RxNewThreadScheduler-3: 9
Pre log RxNewThreadScheduler-1: 1
Pre log RxNewThreadScheduler-2: 4
Pre log RxNewThreadScheduler-4: 16
Pre log RxNewThreadScheduler-5: 25
Post log RxNewThreadScheduler-1: 1
Post log RxNewThreadScheduler-2: 4
Post log RxNewThreadScheduler-3: 9
Post log RxNewThreadScheduler-4: 16
Post log RxNewThreadScheduler-5: 25
Ending parallel executions
Results: 1
Results: 4
Results: 9
Results: 16
Results: 25
编辑:
您可以使用observeOn
更改要侦听结果的线程。例如,如果您想从调用线程进行订阅,则可以将代码更改为以下内容(请参见these答案):
final BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
logger.debug("Starting parallel executions");
// Create an iterable observables
List<Observable<Integer>> observables = calls.stream()
.map(i -> {
return Observable.fromCallable(() -> simpleAsync(i))
.subscribeOn(Schedulers.newThread());
})
.collect(Collectors.toList());
Observable.zip(observables, objects -> { // Zip observables
return Arrays.stream(objects)
.map(Object::toString)
.collect(Collectors.toList());
})
.doOnNext(results -> logger.debug("Ending parallel executions"))
.observeOn(Schedulers.from(tasks::add)) // Add a scheduler with executor from the current thread
.subscribe(results -> { // Subscribe to the result.
// Put your code that needs to "wait"
for (String x : results) {
logger.debug("Results: {}", x);
}
});
try {
tasks.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
答案 1 :(得分:0)
我建议您没有足够的反应:
public Single<List<String>> parallelExecution(List<Integer> calls) {
return Observable
.fromIterable(calls)
.flatMap(val -> Observable.fromCallable(() -> simpleAsync(val).toString())
.subscribeOn(Schedulers.io())
.toList();
}
.toList()
将收集所有结果,并在flatMap
完成后提供一个项目subscribeOn
,而不是observeOn
。 simpleAsync
返回一个反应对象,这会更简单。parallelExecution
不活跃,请使用类似blockingGet
的东西。