Day26:Flow 的运算子 - buffer()

Flow 是依序执行的,如果使用 collect 作为终端运算子,那麽在最後就会按照每一个元素所要花费的时间一一的执行,并把结果吐出来。

如下面的范例:

class Day25 {
    fun flow1() = flow {
        repeat(10) {
            delay(100)
            emit(it)
        }
    }
}

这个 flow 中会产生十个元素,每一个元素都需要花费 100 毫秒建立。

如果这些元素用 collect 执行的时候,也会在每一个元素上花费 200 毫秒来执行,如此一来一个元素所需要执行的时间就是 100 毫秒 + 200 毫秒,总共需要 300 毫秒。

fun main() = runBlocking {
    val day25 = Day25()
    val times = measureTimeMillis {
        day25.flow1()
            .collect {
                delay(200)
                println(it)
            }
    }

    println("$times")
}
0
1
2
3
4
5
6
7
8
9
3115
  • 在这边我们使用 measureTimeMillis 来计算所需执行的时间。
  • 可以看到上面的结果,我们总共花费了 3115 毫秒来执行。

normal flow

Buffer 缓冲

今天要介绍的运算子 buffer 就是要在这个地方使用的,怎麽使用呢?

我们只需要在需要加上缓冲的地方使用即可,如下:

fun main() = runBlocking {
    val day25 = Day25()
    val times = measureTimeMillis {
        day25.flow1()
            .buffer() // Add here
            .collect {
                delay(200)
                println(it)
            }
    }

    println("$times")
}

我把 buffer 加在 flow 与 collect 之间,原因是每一个 flow 的元素需要 100 毫秒来产生,而执行每一个元素却需要 200 毫秒,也就是说,如果我们在这两个操作之间加上缓冲,那麽执行的时间应该可以减少。(因为当 collect 花费 200 毫秒处理第一笔资料时,flow 已经在建立第二笔资料了,这样子就可以减少操作的时间。我们来实际执行一下,看看结果会是如何?

0
1
2
3
4
5
6
7
8
9
2246

经过缓冲之後,我们所需花费的时间由 3115 毫秒,减少至 2246 毫秒。提升了 27% 的速度。

buffer

其实使用 buffer 会变成使用两个 coroutine 在执行,flow 与 collect 分别使用不同的 coroutine ,并且透过 Channel 来传输。

小结

在使用 Flow 时,因为是按照顺序来执行,总时间就会是全部的执行时间加总起来。利用 buffer 我们就可以让这些操作使用不同的 Coroutine,如此一来就可以同时执行多个任务,时间比没有用 buffer 的会少很多。

参考资料

buffer

特别感谢

Kotlin Taiwan User Group

Kotlin 读书会


<<:  Day17_HTML语法14

>>:  不只懂 Vue 语法:为何 v-for 的 key 必须是唯一值?v-for 与 v-if 能否同时使用?

[DAY 24]Embed功能

今天主要是来介绍一下文字嵌入(Embed)这功能 如果想要在讯息里使用mark down功能的话需要...

人脸辨识-day24 模型预测

1.preliminaries 要如何选定特徵与要做甚麽样的分类 step1:要先定做怎样的分类 s...

实体关联性模型图 ER/EER Diagram

ER Diagram (Entity Relationship Model) 是一个非常热门的资料库...

MySQL 字串类型资料之基本操作

VARCHAR & CHAR VARCHAR(0-65535)/CHAR(0-255)差别於...