我在将当前的应用程序从Java转换为Kotlin时遇到了这个问题。
用于使用线程从服务器传输数据的java实现。
它将创建大约100个不同的线程来请求数据,但从我看到的情况来看,一次运行的线程不超过4个,其他线程将等待线程完成后再启动。
在将其翻译为Kotlin时,我使用了协程
这就产生了一个问题,因为服务器显然无法处理实际发送的100个请求。
所有协程都在相同的作用域中启动,所以是这样的:
//this is a custom scope that launches on Dispatchers.IO + a job that I can use to cancel everything
transferScope.launch {
//loadData is a suspending function that returns true/false
val futures = mDownloadJobs.map{ async { it.loadData() } }
val responses = futures.awaitAll()
//check that everything in responses is true etc....
}有没有一种方法可以让特定的transferScope一次只允许5个协程,然后当一个协程结束时,让另一个不同的协程运行?(我不关心顺序)
如果不能通过作用域做到这一点,有没有其他方法可以实现这一点?
发布于 2019-10-17 18:04:16
在提出请求之前,要求每个协程程序从总共5个许可证中获得Kotlin Semaphore许可证。
如下所示:
import kotlinx.coroutines.sync.Semaphore
val requestSemaphore = Semaphore(5)
val futures = mDownloadJobs.map {
async {
// Will limit number of concurrent requests to 5
requestSemaphore.withPermit {
it.loadData()
}
}
}
val responses = futures.awaitAll()发布于 2020-01-24 05:49:34
我相信你应该引导和限制你正在创建的协程的创建。
val channel = Channel<Job>()
transferScope.launch {
mDownloadJobs.forEach { channel.send(it) }
channel.close() // don't forget to close the channel
}
coroutineScope {
val responses = mutableListOf<Any>()
repeat(5).map {
launch {
for (job in mDownloadJobsChannel) {
responses.add(jobs.loadData())
}
}
}
}这种情况下的并行化是5个协程。
我没有测试这段代码:D,我相信有更干净的方法可以做到这一点。
发布于 2019-10-17 17:13:25
您可以这样做,将请求分组为4个块,启动协程来处理它们,并等待该组完成后再启动新的请求。
requests.chunked(4).forEachIndexed { index, chunk ->
coroutineScope {
LOG("processing chunk $index")
chunk.forEach {
launch {
delay(100)
}
}
LOG("done processing $index")
}
}https://stackoverflow.com/questions/58428584
复制相似问题