一.Channel
Channel实际上是一个并发安全的队列,它可以用来连接协程,实现不同协程的通信。
1.Channel的使用
导入依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC-native-mt'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC-native-mt'
在不同协程,用Channel来实现发送与接收。
//Channel的发送与接收
fun testKnowChannel()= runBlocking {
val channel = Channel<Int> ()
//发送者
val launch = GlobalScope.launch {
while (true) {
var i = 0
delay(1000)
//发送
channel.send(++i)
println("send $i")
}
}
//接收者
val launch1 = GlobalScope.launch {
while (true) {
val element = channel.receive()
println("receive $element")
}
}
joinAll(launch,launch1)
}
结果演示:
2.Channel缓冲
Channel实际上就是一个队列,队列中一定存在缓冲区,那么一旦这个缓冲区满了,并且也一直没有人调用receive并取走函数,send就需要挂起。故意让接收端的节奏放慢,发现send总是会挂起,直到receive之后才会继续往下执行。
//Channel的发送与接收
fun testKnowChannel()= runBlocking {
val channel = Channel<Int> ()
//发送者
val launch = GlobalScope.launch {
while (true) {
var i = 0
delay(1000)
channel.send(++i)
println("send $i")
}
}
//接收者 顺序不会变
val launch1 = GlobalScope.launch {
while (true) {
delay(2000)
val element = channel.receive()
println("receive $element")
}
}
joinAll(launch,launch1)
}
结果演示:
我在接收的是延时2秒,比发送的延时长,但并没又造成一次接送多次数据的Channel是有缓冲的
3.迭代Channel
Channel体身确实像序列,所以我们在读取的时候可以直接获取一个Channel的iterator。
//Channel的迭代器
fun testIterateChannel()= runBlocking {
//缓冲大小
val channel = Channel<Int> (Channel.UNLIMITED)
//发送者
val launch = GlobalScope.launch {
for (x in 1..5){
channel.send(x*x)
println("send: ${x * x}")
}
}
//接收者
val launch1 = GlobalScope.launch {
/* val iterator = channel.iterator()//迭代器
while (iterator.hasNext()){
val next = iterator.next()//
println("receive $next")
delay(2000)
}*/
//这是for循环写法
for (element in channel){
println("receive $element")
delay(2000)
}
}
joinAll(launch,launch1)
}
结果演示。
4.produce与actor
1. 构造生产者与消费者的便捷方法。
2. 我们可以通过p℃duce方法启动一个生产者协程,并返回一个ReceiveChanneI,其他协程就可以用这个Channe|来接收数据了。反过来,我们可以用actor启动一个消费者协程。