Kotlin suspend funtion是否在单独的线程上运行?
挂起功能在单独的线程上运行? 如果没有,那么性能优势是什么Kotlin suspend funtion是否在单独的线程上运行?,kotlin,coroutine,kotlinx.coroutines,Kotlin,Coroutine,Kotlinx.coroutines,挂起功能在单独的线程上运行? 如果没有,那么性能优势是什么 suspend fun requestToken():Token {..} // takes 2 sec to complete suspend fun createPost (token:Token){..} // takes 3 sec to complete suspend fun postItem() { val token = requestToken() val post =createPost(tok
suspend fun requestToken():Token {..} // takes 2 sec to complete
suspend fun createPost (token:Token){..} // takes 3 sec to complete
suspend fun postItem() {
val token = requestToken()
val post =createPost(token)
processPost(post)
}
因此,当我们到达processPost(post)时,如果挂起函数没有在单独的线程上运行,那么我们必须等待requestToken()和createPost(token)方法
完成(即2+3=5秒)。按照作者的说法,挂起是异步的,但是如果我们没有产生任何新线程,那么我们如何实现异步行为呢
挂起是异步的
suspend fun
s与调用者同步执行。你实际上想说的是“非阻塞”,这是一个完全不同的故事
但是如果我们没有产生任何新线程,那么我们如何实现异步行为呢
您默认所有I/O都必须在某个级别阻塞。这是错误的。非阻塞I/O的工作原理是将数据推送到发送缓冲区,并在接收缓冲区中有数据时接收通知。
suspend fun
将数据推送到发送缓冲区后挂起自身,并安装回调,当接收缓冲区中的响应数据就绪时,回调将恢复该机制。挂起点只能在协同路由上下文中使用,例如:
fun main() {
delay(1000)
}
无法工作,因为delay
是一个挂起函数,如果没有协同例程,编译器将不知道如何处理该函数。当您有一个协同程序时,它可以使用一个称为dispatcher的东西来控制线程所有权。挂起意味着线程不再用于执行程序的该部分,而是执行其他操作或空闲。它的工作方式是,您可以让多个协程同时工作,而不必为每个协程都有一个线程,该线程可以执行每个协程的一部分,直到挂起点。一般来说,您可以将挂起函数视为“生成器”,它具有生成结果的阶段
suspend fun hello() {
println("Hello")
delay(1000) // suspend here, let someone else use the thread while we wait
println("World")
delay(1000) // suspend again, we can still use the thread while waiting
println("done")
}
每次挂起时,它都会使用线程处理另一个函数,直到该函数挂起且延迟过期,此时该函数最终将继续执行到下一个挂起点或完全完成执行
这与阻塞代码不同,因为它不会通过将线程置于wait状态来浪费线程,而是将其借用到另一个函数。这样就不需要创建其他线程来实现并发性,因为您仍然可以在没有真正并行性的情况下处理多个函数,而是使用函数部分的并发执行
如果你调用Thread.sleep(1000)
它仍然是一个阻塞调用,那么协程不一定能保护你免受阻塞。程序员有责任使用阻塞函数的挂起等价物,以最大限度地提高这个概念的有效性
有关更多详细信息,请阅读,因为它非常详细且有用。可以显式声明线程池的后台单个线程或多个后台线程,然后使用,例如,通过将其作为参数传递,我们将此参数称为“调度程序”。它真正酷的地方是,最初从主线程开始,它会自动切换到调度程序线程,在它上面执行特定的任务,虚拟机在这个地方被挂起或中断,而更酷的事情是,主线程会被解锁,并且可以在有任务的情况下执行其他任务在后台执行任务 一旦任务完成,虚拟机就会返回到它之前被挂起或中断的位置,然后从该位置恢复执行,但现在通过从调度程序的后台线程返回结果,下面是代码片段:
private val backgroundThread = ThreadPoolExecutor(1, 1, 15L, TimeUnit.SECONDS, LinkedBlockingQueue())
GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT) {
postItem(backgroundThread))
}
suspend fun CoroutineScope.postItem(scheduler: ThreadPoolExecutor): Boolean {
val token = requestToken(scheduler)
val post = createPost(token, scheduler)
return processPost(post, scheduler)
}
private suspend fun CoroutineScope.requestToken(scheduler: ThreadPoolExecutor): String {
val def: Deferred<String?> = async(scheduler.asCoroutineDispatcher(), CoroutineStart.DEFAULT) {
val token = networkApi.requestToken()
}
return def.await() ?: ""
}
private suspend fun CoroutineScope.createPost(token: String, scheduler: ThreadPoolExecutor): String {
val def: Deferred<String?> = async(scheduler.asCoroutineDispatcher(), CoroutineStart.DEFAULT) {
val post = networkApi.createPost(token)
}
return def.await() ?: ""
}
private suspend fun CoroutineScope.processPost(post: String, scheduler: ThreadPoolExecutor): Boolean {
val def: Deferred<Boolean?> = async(scheduler.asCoroutineDispatcher(), CoroutineStart.DEFAULT) {
val result = networkApi.processPost(post)
}
return def.await() ?: false
}
private val backgroundThread=ThreadPoolExecutor(1,1,15L,TimeUnit.SECONDS,LinkedBlockingQueue())
GlobalScope.launch(Dispatchers.Main、CoroutineStart.DEFAULT){
postItem(背景线程))
}
suspend-fun-CoroutineScope.positem(调度程序:ThreadPoolExecutor):布尔值{
val token=requestToken(调度程序)
val post=createPost(令牌、调度程序)
返回processPost(post、调度程序)
}
private suspend fun CoroutineScope.requestToken(调度程序:ThreadPoolExecutor):字符串{
val def:Deferred=async(scheduler.ascoroutinedpatcher(),CoroutineStart.DEFAULT){
val token=networkApi.requestToken()
}
返回def.await()?:“”
}
createPost(令牌:String,调度程序:ThreadPoolExecutor):String{
val def:Deferred=async(scheduler.ascoroutinedpatcher(),CoroutineStart.DEFAULT){
val post=networkApi.createPost(令牌)
}
返回def.await()?:“”
}
processPost(post:String,scheduler:ThreadPoolExecutor):布尔值{
val def:Deferred=async(scheduler.ascoroutinedpatcher(),CoroutineStart.DEFAULT){
val结果=networkApi.processPost(post)
}
返回def.await()?:false
}
在大多数情况下,协程调度器不执行任何调度,您应该阅读。它只确保协同路由被分派到其关联的执行模块(例如,GUI事件循环或ExecutorService)。然后,执行模块决定如何调度它。调度意味着计划任务的执行,这正是所谓调度程序的工作。它计划何时何地执行任务,而ExecutorService只是用于执行任务的资源。调度器是决定资源使用方式的一个,就像调度器一样。当然,你可以随意查看它,但实际上它被称为一个调度器,而这个名称适合的原因如下所述。在大多数情况下,协同路由调度器只执行调度而不执行调度,这是因为协同路由