channel用于协程之间的通讯,使用send和receive往通道里写入或者读取数据,2个方法为非阻塞挂起函数,channel是热流,不管有没有订阅者都会发送。
Channel的简单使用
val channel = Channel<Int>()
launch {
channel.send(111)
}
launch {
println("receive:" + channel.receive())
}
打印 receive:111
Channel 默认是0容量的buffer
send是个挂起函数,发送到通道,如果通道buffer已满,就会挂起调用者
例如:
val channel = Channel<Int>()
launch {
channel.send(111)
println("sendbefore:222")
channel.send(222)
println("sendafter:222")
channel.send(333)
}
launch {
println("receive:" + channel.receive())
}
打印
receive:111
sendbefore:222
channel.send(222) 发送到通道后,通道满了,调用者的协程被挂起,所以 println("sendafter:222")不执行了
recevie调用时,如果通道里不为空,就从通道里把元素拿出来,并且从通道里移除元素,如果通道元素为空,则挂起调用者,等通道有元素后 才会执行
例如
val channel = Channel<Int>()
launch {
delay(5000)
channel.send(111)
}
launch {
println("receive:before")
println("receive:" + channel.receive())
println("receive:after")
}
打印
2022-08-17 16:21:24.918 7723-7723/com.kemai.myapplication I/System.out: receive:before
2022-08-17 16:21:29.924 7723-7723/com.kemai.myapplication I/System.out: receive:111
2022-08-17 16:21:29.924 7723-7723/com.kemai.myapplication I/System.out: receive:after
receive:before和 receive:111 间隔了5秒
receive时 通道里没有元素,被挂起,5秒后发送了元素,继续执行
Channel迭代获取
lifecycleScope.launch {
channel.send(1)
channel.send(2)
}
lifecycleScope.launch {
for(x in channel){
println(x)
}
println("receive:end" )
}
打印
1
2
接受者一直在等待,所以不打印 receive end
在send完毕后,调用channel.close即可执行完毕,打印receive end
Channel的四种类型
Rendezvous channel(默认类型): 0尺寸buffer,send是个挂起函数,发送到通道,如果通道buffer已满,就会挂起调用者,这个0buffer,发送一个,如果没人接收,调用者就被挂起
Buffered channel:指定元素大小,发送当buffer满了后Send会被挂起。
Conflated channel: 新元素会覆盖旧元素,receiver只会得到最新元素,Send永不挂起。
Unlimited channel: buffer无限,Send不被挂起。
例子:
1 Rendezvous channe
val rendezvousChannel = Channel<Int>(Channel.RENDEZVOUS)
lifecycleScope.launch {
rendezvousChannel.send(1)
println("after send 1111")
rendezvousChannel.send(2)
println("after send 2222")
}
lifecycleScope.launch {
println(rendezvousChannel.receive())
println("receive:end")
}
//打印1
//receive:end
//after send 1111
//rendezvousChannel 发送了1后,接受了1,继续发送2,因为buffer是0,所以满了,2没人接收,所以调用者被挂起,没有打印after send 2222
2 Buffered channel
val bufferedChannel = Channel<Int>(2)
lifecycleScope.launch {
bufferedChannel.send(1)
println("after send 1111")
bufferedChannel.send(2)
println("after send 2222")
bufferedChannel.send(3)
println("after send 3333")
bufferedChannel.send(4)
println("after send 4444")
}
lifecycleScope.launch {
println(bufferedChannel.receive())
println("receive:end")
}
//打印
//after send 1111
//after send 2222
//1
//receive:end
//after send 3333
//bufferedChannel(2) 发送了1后,接受了1,继续发送2 3 4,因为buffer是2,发送了2和3后,所以满了,2没人接收,所以调用者被挂起,没有打印after send 4444
3 Conflated channel
val conflatedChannel = Channel<Int>(Channel.CONFLATED)
lifecycleScope.launch {
for (x in 1..10) {
conflatedChannel.send(x)
}
}
lifecycleScope.launch {
println(conflatedChannel.receive())
println("receive:end")
}
//打印10 只会接收最新值 但是在2次send之间delay1毫秒,会取第一次的,应该机制是send被挂起之前的最新值,挂起后 就算另外一批次的发送了
4 Unlimited channel
val unlimitedChannel = Channel<Int>(Channel.UNLIMITED)
lifecycleScope.launch {
for (x in 1..10) {
unlimitedChannel.send(x)
println(x)
}
}
lifecycleScope.launch {
println(unlimitedChannel.receive())
println(unlimitedChannel.receive())
println("receive:end")
}
//打印send 1-10 只会接收最新值 receive 1-2 receive end, send方法不会挂起,因为buffer无限大,不会被填满