我有一个雇员列表,我想为每个雇员打API。在同步模式下,这需要花费很多时间,我想使用协同程序来提高性能。这是我到目前为止所做的:
fun perform() = runBlocking {
employeesSource.getEmployees()
.map { launch { populateWithLeaveBalanceReports(it) } }
.joinAll()
}
suspend fun populateWithLeaveBalanceReports(employee: EmployeeModel) {
println("Start ${COUTNER}")
val receivedReports = reportsSource.getReports(employee.employeeId) // call to a very slow API
receivedReports { employee.addLeaveBalanceReport(it) }
println("Finish ${COUTNER++}")
}
当我尝试运行此代码时,代码正在同步运行,并且在控制台中,我看到以下输出:
Start 0
Finish 0
Start 1
Finish 1
Start 2
Finish 2
表示调用是按顺序进行的。如果我将populateWithLeaveBalanceReports
函数中的整个代码替换为delay(1000)
,它将异步运行:
Start 0
Start 0
Start 0
Finish 0
Finish 1
Finish 2
我在做什么错?有什么想法吗?
答案 0 :(得分:3)
协程不会神奇地将您的阻止网络API变为非阻止。使用launch(Dispatchers.IO) { ... }
在弹性线程池中运行阻塞任务。只需注意,这并没有比普通的executorService.submit(blockingTask)
做更多的事情。由于它使用了预先构建的全局线程池,因此更加方便。
答案 1 :(得分:0)
这些行可能正在使用阻塞代码-该代码依赖于阻塞线程来等待任务完成。
val receivedReports = reportsSource.getReports(employee.employeeId)
receivedReports { employee.addLeaveBalanceReport(it) }
很可能您在reportsSource.getReports
调用下使用了非异步http客户端或jdbc驱动程序。
如果是这样,您应该
reportsSource.getReports
的代码,因此它不会依赖任何阻止代码。这是新的/非阻塞/具有挑战性的方式