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 {
    val channel = Channel()
    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 {
    val channel = Channel()
    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 = produce {
    for (value in 1..5) send(value * value)
}
fun main() = runBlocking {
    val squares = produceSquares()
    squares.consumeEach { println(it) }
    println("Done!")
}

4、Pipelines

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

 

 

 

你可能感兴趣的:(Kotlin协程,kotlin,协程,channel)