协程 Kotlin 中 Job 和 Deferred 的区别

Difference between Job and Deferred in Coroutines Kotlin

我是协程的新手,我理解 launchasync 但仍然令人困惑的部分是 DeferredDeferred 是什么? JobDeferred 之间的差异。清晰的解释和示例更有帮助。提前致谢。

所以 job 是一种表示协程执行的对象,与 structured concurrency 相关,例如您可以取消一个作业,这个作业的所有子作业也将被取消。

来自 docs:

Job is a cancellable thing with a life-cycle that culminates in its completion.

Deferred 是 Java 中 Future 的某种模拟:封装了一个操作,该操作将在初始化后的某个时间点完成。但也与 Kotlin 中的协程有关。

来自文档:

Deferred value is a non-blocking cancellable future — it is a Job that has a result.

所以,Deferred 是一个 Job,结果是:

A deferred value is a Job. A job in the coroutineContext of async builder represents the coroutine itself.

一个例子:

someScope.launch {
    val userJob: Deferred<User> = async(IO) { repository.getUser(id) }
    //some operations, while user is being retrieved 
    val user = userJob.await() //here coroutine will be suspended for a while, and the method `await` is available only from `Deferred` interface
    //do the job with retrieved user
}

此外,可以使用现有范围构建此 async 请求,但这是另一个问题。

在基本层面上,Deferred 是一个未来。它使一个协程可以等待另一个协程产生的结果,并暂停自身直到准备就绪。调用 async 是获得 Deferred.

的一种方法,但到目前为止并不是唯一的方法

但是,我认为您的问题更多是关于基础知识:何时使用 launch,何时使用 async-await。这是一个重要的教训:你可能不需要异步。人们倾向于使用它是因为关键字 asyncawait 在其他语言中很熟悉,但在 Kotlin 中,async 并不是实现非阻塞调用的通用工具。

这里有一个关于如何将阻塞调用变成暂停、非阻塞调用的基本方法:

uiScope.launch {
    val ioResult = withContext(Dispatchers.IO) { blockingIOCall() }
    ... just use the result, you're on the GUI thread here.
}