返回

kotlin协程官方文档(6)-通道

Android

协程通道是一种轻量级管道,用于协程之间发送和接收数据。通道可以用来在并发协程之间进行通信,也可以用来在协程和主线程之间进行通信。

通道与队列非常相似,但也有几个关键的区别:

  • 通道可以关闭,以此来表明元素已发送完成。
  • 在接收方,使用常规的 for 循环从通道接收元素是比较方便的。
  • 从概念上讲,close 类似于向通道发送一个特殊的 cloase 标记。一旦接收到这个 close 标记,迭代就会停止,因此可以保证接收到 close 之前发送的所有元素。

通道的创建

要创建通道,可以使用 Channel 接口的工厂方法 create()。该方法有两个参数:

  • 容量:通道的容量,即通道中可以同时容纳多少个元素。如果容量为 0,则通道将是一个无缓冲通道。无缓冲通道只能在发送方和接收方都准备好的情况下才能进行通信。
  • 元素类型:通道中元素的类型。

例如,以下代码创建了一个无缓冲通道,用于发送和接收字符串:

val channel = Channel<String>()

发送数据

要向通道发送数据,可以使用 send() 方法。send() 方法会将数据放入通道中,如果通道已满,则会阻塞发送方,直到通道中有空间容纳数据。

例如,以下代码将字符串 "Hello, world!" 发送到通道中:

channel.send("Hello, world!")

接收数据

要从通道接收数据,可以使用 receive() 方法。receive() 方法会从通道中接收数据,如果通道为空,则会阻塞接收方,直到通道中有数据可供接收。

例如,以下代码从通道中接收一个字符串:

val message = channel.receive()

关闭通道

当不再需要通道时,可以调用 close() 方法来关闭通道。close() 方法会将一个特殊的 close 标记发送到通道中,并使通道无法再接收数据。

例如,以下代码关闭通道:

channel.close()

使用 for 循环从通道接收数据

使用 for 循环从通道接收数据是一种非常方便的方式。for 循环会自动处理通道的关闭,并在通道关闭后自动停止迭代。

例如,以下代码使用 for 循环从通道中接收字符串:

for (message in channel) {
  println(message)
}

通道的缓冲区大小

通道的缓冲区大小决定了通道可以同时容纳多少个元素。如果通道的缓冲区大小为 0,则通道将是一个无缓冲通道。无缓冲通道只能在发送方和接收方都准备好的情况下才能进行通信。

如果通道的缓冲区大小大于 0,则通道将是一个有缓冲通道。有缓冲通道可以存储多个元素,因此发送方和接收方可以独立于对方进行操作。

选择通道

如果有多个通道,可以使用 select() 方法来选择一个通道进行通信。select() 方法会阻塞当前协程,直到有一个通道准备就绪。

例如,以下代码使用 select() 方法从两个通道中接收数据:

val channel1 = Channel<String>()
val channel2 = Channel<String>()

select {
  channel1.onReceive { message ->
    println("Received $message from channel1")
  }
  channel2.onReceive { message ->
    println("Received $message from channel2")
  }
}