6、通道(Channels)

本节介绍通道----Channels(官方文档)

Deferred values提供了一种在协程之间传递单个值的简便方式,通道(channels)则提供了在协程间传递流的方法。

1、Channel basics

熟悉Java的读者应该都知道阻塞队列BlockingQueue,而这里说的通道在概念上则与BlockingQueue非常相似,一个重要的区别是通道使用的是suspend的send方法存储数据而BlockingQueue使用的是阻塞的put方法,同时在取数据的时候通道使用的是suspend的receive而BlockingQueue使用是阻塞的take,代码如下:

package com.cool.cleaner.test

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking


fun main() = runBlocking<Unit> {
    val channel = Channel<Int>()
    launch {
        /**
         * this might be heavy CPU-consuming computation or async logic,
         * we'll just send five squares.
         */
        for (x in 1..5) channel.send(x * x)
    }
    // here we print five received integers:
    repeat(5) {
        println(channel.receive())
    }
    println("Done!")
}

输出如下:

1
4
9
16
25
Done!

Process finished with exit code 0

2、通道的关闭及迭代

与队列不一样的是通道可以被关闭以表示没有元素会再被发射出去,在接收端可以使用for循环方便地接收通道里面的数据。

从概念上讲close就像是发射了一个特殊的标识(token)到通道中,在接收端只要收到相应的token就会马上结束迭代,所以就可以保证在token发射之前的所有数据都会被接收到,如下代码所示:

package com.cool.cleaner.test

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking


fun main() = runBlocking<Unit> {
    val channel = Channel<Int>()
    launch {
        for (x in 1..9) {
            if (x >= 7) {
                channel.close()//we're done sending
                break
            } else {
                channel.send(x * x)
            }
        }
    }
    // here we print received values using 'for'
    // loop(until the channel is closed)
    for (value in channel) {
        println(value)
    }
    println("Done!")
}

3、通道生产者(Building channel producers)

在协程中生成一系列的元素这种模式是非常普遍的,这是在并发编程中经常遇到的生产者----消费者模式的一部分;你可以将通道作为参数传递给一个函数并封装成一个生产者,但是这违背了结果必须从函数中返回的一种认知常识。

在协程中有一个协程构建器produce可以使得构建生产者更容易,而扩展函数consumeEach则作为消费者端替代了for循环的功能,代码如下:

package com.cool.cleaner.test

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.runBlocking

fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (value in 1..5) send(value * value)
}
fun main() = runBlocking<Unit> {
    val squares = produceSquares()
    squares.consumeEach { println(it) }
    println("Done!")
}

4、Pipelines

一个pipeline就是一个协程产生无限(可能)的值,代码如下:

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值