kotlin协程官方文档(6)-通道
2024-01-28 15:31:29
协程通道是一种轻量级管道,用于协程之间发送和接收数据。通道可以用来在并发协程之间进行通信,也可以用来在协程和主线程之间进行通信。
通道与队列非常相似,但也有几个关键的区别:
- 通道可以关闭,以此来表明元素已发送完成。
- 在接收方,使用常规的 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")
}
}