Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin suspend funtion是否在单独的线程上运行?_Kotlin_Coroutine_Kotlinx.coroutines - Fatal编程技术网

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只是用于执行任务的资源。调度器是决定资源使用方式的一个,就像调度器一样。当然,你可以随意查看它,但实际上它被称为一个调度器,而这个名称适合的原因如下所述。在大多数情况下,协同路由调度器只执行调度而不执行调度,这是因为协同路由