跳至主要內容

分析协程内部工作逻辑

guodongAndroid大约 2 分钟

分析协程内部工作逻辑

fun fetchUser(userId: String) {
    val user = userService.getUser(userId) // 1
    print("Fetching user") // 2
    print(user.name) // 3
    print("Fetched user") // 4
}

这并不是真正的黑魔法——只是一种使用低级处理方式的智能方法。getUser 被标记为可挂起的函数,这意味着系统准备在后台调用它,你将 会得到一个未完成的包装好的 “卷饼”。但它可能还没有被执行。系统会把它添加进线程池中,在线程池中它将等待执行。一旦你准备好吃 “卷饼” 并请求结果,程序就会阻塞,直到你立刻得到结果,或者在协程中挂起并等待结果。

明白了这一点后,程序就可以跳过其他的代码,直到程序走到使用 user 的第一行代码处。这称为等待结果。此时,将执行 getUser,如果 getUser 还没有执行,程序将挂起。

这意味着可以在调用 getUser 和使用其结果(user)之间做一些你想做的事。因为编译器知道挂起点和可挂起函数是异步的,并按顺序处理它们的执行,所以你可以编写易于理解和简洁的代码。这将使你的代码具有非常好的可扩展性且易于维护。

由于使用协程编写异步代码非常简单,所以你可以轻松组合多个请求或者数据转换。不需要其他的方式,不需要奇怪的流来映射传递数据,也不需要组合复杂的运算符或转换结果。你需要做的就是将函数标记为挂起函数,并在协程块中调用它们。

关于协程的另一件极其重要的事情是它们不是线程。协程利用线程池在多个现有线程之间混合工作。你创建数百万个协程,而不用担心内存溢出。一百万个线程会占用非常多的内存,即使是当今最先进的计算机也会因此而崩溃。

虽然很多语言已经支持了协程,但是它们的实现不尽相同。