Kotlin协程Channel(通道)

一、认识Channel(热流)

协程中的通道(Channel)是一种用于在协程之间传输数据的机制。通道可以被看作是生产者-消费者模式的实现,其中一个协程可以发送数据到通道,而另一个协程则可以从通道接收数据。通道具有缓冲区,允许在发送者和接收者之间进行异步通信。

与Flow冷流的区别:Channel热流的特点是,数据流在创建后立即开始,不受订阅者的影响,而Flow 是一种冷流,这意味着它的数据流在没有订阅者时是不会启动的

 Chnannel的协程通信实例:

 @Test
    fun testchannel() = runBlocking {
        val channel = Channel<Int>()
        //生产者
        val producer = GlobalScope.launch {
            var i = 0
            while (true){
                delay(1000)
                channel.send(++i)
                println("send $i")
            }
        }
        //消费者
        val  consumer = GlobalScope.launch {
            while (true) {
                val element = channel.receive()
                println("receive $element")
            }
        }
        joinAll(producer, consumer)
    }

结果如下,


二、Channel的容量

默认情况下,Channel的容量是0,就是发出一个才能接收一个


三、Channel迭代

1.使用 for (element in channel) 的形式可以从通道中依次获取元素,直到通道被关闭或者没有更多元素可用为止。

2.使用iterator迭代器

实例代码如下:

   fun testchannel() = runBlocking {
        val channel = Channel<Int>(Channel.UNLIMITED)
        //生产者
        val producer = GlobalScope.launch {
            for (i in 1..5){
                channel.send(i * i)
                println("send ${i * i}")
            }
        }
        //消费者
        val  consumer = GlobalScope.launch {
           val iterator = channel.iterator()
            while (iterator.hasNext()){
                val element = iterator.next()
                println("receive $element")
                delay(2000)
            }
        }
        joinAll(producer, consumer)
    }
   @Test
    fun testchannel() = runBlocking {
        val channel = Channel<Int>(Channel.UNLIMITED)
        //生产者
        val producer = GlobalScope.launch {
            for (i in 1..5){
                channel.send(i * i)
                println("send ${i * i}")
            }
        }
        //消费者
        val  consumer = GlobalScope.launch {
           val iterator = channel.iterator()
            for (element in channel){
                println("receive $element")
                delay(2000)
            }
        }
        joinAll(producer, consumer)
    }


四、produce与actor

 @Test
    fun testchannel1() = runBlocking {
        //生产者便捷方式
        val receiveChannel: ReceiveChannel<Int> = GlobalScope.produce {
            repeat(100){
                delay(1000)
                send(it)
            }
        }
        //消费者
        val  consumer = GlobalScope.launch {
           for (i in receiveChannel){
               println("receive: $i")
           }
        }
        consumer.join()
    }


五、Channel的关闭 

就字面意思,上面讲的很清楚了,我用一个事例代码解释一下

 @Test
    fun testchannel3() = runBlocking {
        val channel = Channel<Int>(3)//设置通道为3
        //生产者
        val producer = GlobalScope.launch {
            List(3) {
                channel.send(it)
                println("send $it")
            }
            channel.close()
            println("Befor CloseForSend: ${channel.isClosedForSend}" + " "+
                    "CloseForReceive: ${channel.isClosedForReceive}")
        }
        //消费者
        val  consumer = GlobalScope.launch {
            val iterator = channel.iterator()
            for (element in channel){
                println("receive $element")
                delay(1000)
            }
            println("After CloseForSend: ${channel.isClosedForSend}" +" "+
                    "CloseForReceive: ${channel.isClosedForReceive}")
        }
        joinAll(producer, consumer)
    }

结果:

可见,在关闭的时候,只接收到0,而1,2没有接收到,所以CloseForSend: true CloseForReceive: false,等到1, 2也被接收的时候 CloseForReceive也为true了

六、BroadcastChannel(广播通道一对多)

通过调用 openSubscription 函数可以创建一个用于接收消息的 ReceiveChannel(相当订阅)

 就是通过订阅的方式来实现一对多的传播。

  @Test
    fun testchannel4() = runBlocking {
        val broadcastChannel = BroadcastChannel<Int>(Channel.BUFFERED)//设置通道为3
        //生产者
        val producer = GlobalScope.launch {
            List(3) {
               delay(1000)
                broadcastChannel.send(it)
            }
            broadcastChannel.close()//发送完成后关闭
        }
        //广播接收
        List(3){index ->
            GlobalScope.launch {
                val receiveChannel = broadcastChannel.openSubscription()
                for (i in receiveChannel){
                    println("$i")
                }
            }
        }.joinAll()
    }

  • 40
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Imagine8877

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值