24-通道基础
12.6.1 通道基础
通道(Channel)从概念上来讲,非常类似于Java的阻塞队列(BlockingQueue)。BlockingQueue位于Java的Concurrent中,使用它可以有效地解决多线程中要求的高效安全的数据传输问题。BlockingQueue有两个常用的方法。
- take():取走BlockingQueue中排在首位的对象,如果BlockingQueue为空,则阻塞队列进入等待状态,直到BlockingQueue中有新的数据加入。
- put(E e):将对象e添加到BlockingQueue中,如果BlockQueue没有空间,则调用该方法的线程会被阻塞,直到BlockingQueue里面有空间再继续。
二者的关键区别在于,通道支持挂起操作,而不是被阻塞,同时通道还可以被关闭。代码如下。
fun main(args: Array<String>) = runBlocking {
val channel = Channel<Int>()
launch {
// 模拟CPU耗时计算或异步逻辑处理
for (x in 1..5) channel.send(x * x)
}
// 打印5个接收到的整数
repeat(5) { println(channel.receive()) }
println("Done!")
}
运行上面的代码,输出的结果如下。
1
4
9
16
25
Done!
在上面的实例中,Channel调用的是会合通道RendezvousChannel()。会合通道中没有任何缓冲区,调用send函数时通道被挂起,直到另一个协程调用receive函数,然后receive函数挂起,直到另一个协程调用send函数,这是一个完全无锁的实现。