线程

  • 线程并非廉价的。线程需要昂贵的上下文切换。
  • 线程不是无限的。可被启动的线程数受底层操作系统的限制。在服务器端应用程序中,这 可能会导致严重的瓶颈。
  • 线程并不总是可用。在一些平台中,比如 JavaScript 甚至不支持线程。
  • 线程不容易使用。线程的 Debug,避免竞争条件是我们在多线程编程中遇到的常见问题。

回调

fun postItem(item: Item) {
    preparePostAsync { token ->
        submitPostAsync(token, item) { post ->
            processPost(post)
        }
    }
}
 
fun preparePostAsync(callback: (Token) -> Unit) {
    // 发起请求并立即返回
    // 设置稍后调用的回调
}
  • 回调嵌套的难度。通常被用作回调的函数,经常最终需要自己的回调。这导致了一系列回 调嵌套并导致出现难以理解的代码。该模式通常被称为标题圣诞树(大括号代表树的分 支)。
  • 错误处理很复杂。嵌套模型使错误处理和传播变得更加复杂。

Futures,Promises 等等

futures 或 promises 背后的想法(这也可能会根据语言/平台而有不同的术语),是当我 们发起调用的时候,我们承诺在某些时候它将返回一个名为 Promise 的可被操作的对象。

  • 不同的编程模型。与回调类似,编程模型从自上而下的命令式方法转变为具有链式调用的 组合模型。传统的编程结构例如循环,异常处理,等等。通常在此模型中不再有效。
  • 不同的 API。通常这需要学习完整的新 API 诸如 thenCompose 或 thenAccept,这也可 能因平台而异。
  • 具体的返回值类型。返回类型远离我们需要的实际数据,而是返回一个必须被内省的新类 型“Promise”。
  • 异常处理会很复杂。错误的传播和链接并不总是直截了当的。

响应式编程

响应式编程和处理数据项的异步流有关,当有数据出现时应用会做出相应的处理。数据流的 本质是一系列随时间发生的数据项,而且数据流是可以被观察的。

响应式编程模型中有一个发送者和一个接收者,发送者发送数据流,接收者进行异步接收:

协程

Kotlin 编写异步代码的方式是使用协程,这是一种计算可被挂起的想法。即一种函数可以 在某个时刻暂停执行并稍后恢复的想法。

协程的一个好处是,当涉及到开发人员时,编写非阻塞代码与编写阻塞代码基本相同。编程 模型本身并没有真正改变。