如何实施一个有限的调用与改造阻塞客户端和协程

我有以下代码:

val context = newFixedThreadPoolContext(nThreads = 10, name="myThreadPool") val total = 1_000_000 //can be other number as well val maxLimit = 1_000 return runBlocking { (0..total step maxLimit).map { async(context) { val offset = it val limit = it + maxLimit blockingHttpCall(offset, limit) } }.flatMap { it.await() }.associateBy { ... }.toMutableMap() } 

我想只有10个电话同时发生阻塞的API。 但是,上面的代码似乎没有按照我的预期(我认为所有的调用立即开始),或者至少我不明白,如果它。
什么是实施它的正确方法? 如果我使用改造的异步api,相同的解决方案将工作吗?

我不知道你的情况,但最简单的方法 – 使用OkHttp API来配置并发级别,例如,这是OkHttp的默认并发策略

但是,如果您将自己的Dispatcher实例设置为OkHttpClient.Builder则可以拥有自己的策略

当然,你也可以使用协程

您当前的实现是不正确的,因为您为每个项目创建协程调度程序,但共享线程池所有协程应该使用相同的调度程序,只需将newFixedThreadPoolContext外的newFixedThreadPoolContext创建(现在有1000个调度程序,每个有10个线程)。

但我不建议你使用协程+阻塞调用,最好是配置OkHttp并发(更灵活),并使用协调与非阻塞调用(你可以写自己的适配器或使用现有的库,如kotlin-coroutines-retrofit ) 。 它将允许你混合你的http请求和UI代码或其他任务。

所以如果你使用非阻塞的API + OkHttp内部并发性,你不需要特殊的代码来控制并发性,当然,你可以像上面例子中那样限制并发调用的数量(带有固定的调度器构造),但是我真的不认为这是有道理的,因为你可以降低并发级别,而不是增加它。

移动到非阻塞API后,您可以在任何协同程序调度程序中并行运行所有协同程序(即使在UI线程中),也可以在不阻塞的情况下等待结果。

此外,使用OkHttpClient配置的隐式控制并发性在体系结构方面看起来更为正确(可以使用DI代码来配置Retrofit + OkHttp并使用预配置的并发策略将其提供给客户端代码)。 当然,你可以用其他方法来实现,但是这个对我来说更自然一些。