channel用于協(xié)程之間的通訊您单,使用send和receive往通道里寫入或者讀取數(shù)據(jù)梯投,2個(gè)方法為非阻塞掛起函數(shù)稻薇,channel是熱流押桃,不管有沒有訂閱者都會發(fā)送葵萎。
Channel的簡單使用
val channel = Channel<Int>()
launch {
channel.send(111)
}
launch {
println("receive:" + channel.receive())
}
打印 receive:111
Channel 默認(rèn)是0容量的buffer
send是個(gè)掛起函數(shù),發(fā)送到通道唱凯,如果通道buffer已滿羡忘,就會掛起調(diào)用者
例如:
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) 發(fā)送到通道后,通道滿了磕昼,調(diào)用者的協(xié)程被掛起卷雕,所以 println("sendafter:222")不執(zhí)行了
recevie調(diào)用時(shí),如果通道里不為空票从,就從通道里把元素拿出來漫雕,并且從通道里移除元素,如果通道元素為空峰鄙,則掛起調(diào)用者浸间,等通道有元素后 才會執(zhí)行
例如
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時(shí) 通道里沒有元素,被掛起吟榴,5秒后發(fā)送了元素魁蒜,繼續(xù)執(zhí)行
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完畢后,調(diào)用channel.close即可執(zhí)行完畢兜看,打印receive end
Channel的四種類型
Rendezvous channel(默認(rèn)類型): 0尺寸buffer锥咸,send是個(gè)掛起函數(shù),發(fā)送到通道铣减,如果通道buffer已滿她君,就會掛起調(diào)用者,這個(gè)0buffer葫哗,發(fā)送一個(gè)缔刹,如果沒人接收,調(diào)用者就被掛起
Buffered channel:指定元素大小劣针,發(fā)送當(dāng)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 發(fā)送了1后引谜,接受了1,繼續(xù)發(fā)送2擎浴,因?yàn)閎uffer是0员咽,所以滿了,2沒人接收贮预,所以調(diào)用者被掛起贝室,沒有打印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) 發(fā)送了1后,接受了1仿吞,繼續(xù)發(fā)送2 3 4滑频,因?yàn)閎uffer是2,發(fā)送了2和3后唤冈,所以滿了峡迷,2沒人接收,所以調(diào)用者被掛起你虹,沒有打印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毫秒凉当,會取第一次的,應(yīng)該機(jī)制是send被掛起之前的最新值售葡,掛起后 就算另外一批次的發(fā)送了
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方法不會掛起看杭,因?yàn)閎uffer無限大,不會被填滿