我试图查询为我提供要下载的文件列表的API(如下所示)。然后我继续下载这些文件,同时还要重新查询API以查找初始调用中可能遗漏的任何内容。
Completable#mergeDelayError(Iterable<? extends CompletableSource> sources)
用于确保我可以并行执行多个任务,并在完成所有任务后收到通知。
fun fetchAndDownload(details: List<String>): Completable =
exampleApi.fetchPackages(details) // This is a Single
.flatMapCompletable { (results, retry) ->
val completables = mutableListOf<Completable>()
results.mapTo(completables) { value ->
exampleApi.download(value).subscribeOn(Schedulers.io())
}
if (retry.isNotEmpty()) {
completables += fetchAndDownload(retry)
.delay(3L, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
}
Completable.mergeDelayError(completables)
}
但是,这种实现有可能通过一次执行太多事情来压倒网络和/或线程数。因此,我想知道限制一次运行的completables
的最佳方法是什么。
我知道Completable#mergeDelayError(Publisher<? extends CompletableSource> sources, int maxConcurrency)
但不确定如何将List<Completable>
转换为所需的Publisher
。另一种解决方案是提供具有最大线程数的自定义Scheduler
,但我也不确定如何提供这样的Schduler
(我可以在不再需要时清理和丢弃)
答案 0 :(得分:2)
最简单的方法是使用Floable.fromIterable
将List
Completable
转换为Publisher
。
这将允许使用Completable#mergeDelayError(Publisher<? extends CompletableSource> sources, int maxConcurrency)
答案 1 :(得分:1)
您可以将 flatMap 与 maxConcurrent 值一起使用,然后让您的管道同步运行。
@Test
public void asyncFlatMapWithMaxConcurrent() {
Observable.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
.flatMap(value -> Observable.just(value)
.map(number -> {
try {
Thread.sleep(1000);
System.out.println(String.format("Value %s in Thread execution:%s",number, Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
}
return number;
}).subscribeOn(Schedulers.newThread())
, 2)//This is the max concurrenrt
.subscribe();
new TestSubscriber()
.awaitTerminalEvent(15, TimeUnit.SECONDS); }
如果你看到flatMap函数之后的第二个参数,我们传递一个值2,它是可以为该flatMap运行的最大并发线程数
您可以在此处查看示例等内容。