前言

Flow 是一种冷流,只有 collect 的时候才会产生数据,而 SharedFlow、StateFlow 虽然是热流,但是,每次 collect 的时候,要么是只能获取最新值,要么把之前存储的值重新都发一遍。有没有一种热流,能更像生产者与消费者,一个专门生产,一个专门消费,答案当然是有的,那便是 Channel。

Channel 的使用

        GlobalScope.launch {launch {(1..3).forEach { value ->println("channel 生产了 $value")channel.send(value)delay(100)}}launch {repeat(3){delay(1000)val value = channel.receive()println("channel 消费了 $value")}}}

日志:

I/System.out: channel 生产了 1
I/System.out: channel 消费了 1
I/System.out: channel 生产了 2
I/System.out: channel 消费了 2
I/System.out: channel 生产了 3
I/System.out: channel 消费了 3

容量

在这里,我特意让生产速度慢于消费速度,但是会发现,即使如此,还是生产一个,消费一个,这说明了 channel 内部是有容量的,所以需要等到消费者取走后才会生产继续生产,若我们需要扩大该容量,可以在创建 channel 的时候,赋予其初始容量:

val channel = Channel<Int>(2)

参数说明

其实,容量的配置也只是其参数配置的一部分,下面我们来完整看看其说明:

public fun <E> Channel(capacity: Int = RENDEZVOUS,onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND,onUndeliveredElement: ((E) -> Unit)? = null
): Channel<E>
  • capacity:容量配置,当其赋值大于等于 1 的时候,就是设置相应的容量,当其小于1 的时候,进行额外处理,并有相应的常数:

    • RENDEZVOUS:默认值,值为 0,标识没有缓冲区。
    • CONFLATED:值为 -1,创建一个 合并 channel。
    • BUFFERED:值为 -2,对于支持挂起的 channel,设置其容量为 64,对于不支持挂起的 channel,其容量为 1。
    • UNLIMITED:值为 Int.MAX_VALUE,设置为无限容量的 channel。
  • onBufferOverflow:当超过缓冲区的时候,如何进行处理:
    • SUSPEND:进行挂起操作。
    • DROP_OLDEST:不挂起,直接移除最旧的值。
    • DROP_LATEST:不挂起,直接移除最新的值。
  • onUndeliveredElement:当生产数据后,因为其它原因导致未能交付给消费者,这些数据则会进入该函数。这样要特别注意,因为 DROP_OLDEST 和 DROP_LATEST 丢失的数据并不会进入该函数,一般为 cancel()close() 或者出现异常之类的,才会进入该函数。

下面,我们写个小栗子来说明这个参数的作用:

        val channel = Channel<Int>(2, BufferOverflow.DROP_OLDEST){ value ->println("$value 没有被正常消费")}GlobalScope.launch {launch {(1..5).forEach { value ->println("channel 生产了 $value")channel.send(value)delay(100)}}launch {repeat(5){delay(1000)val value = channel.receive()println("channel 消费了 $value")}}}

日志输出:

I/System.out: channel 生产了 1
I/System.out: channel 生产了 2
I/System.out: channel 生产了 3
I/System.out: channel 生产了 4
I/System.out: channel 生产了 5
I/System.out: channel 消费了 4
I/System.out: channel 消费了 5

这里可以看出,生产了 1、2、3、4、5,但是只消费了 4、5,至于 1、2、3 都因为 DROP_OLDEST 被丢弃了,并且没有回调到 onUndeliveredElement。

我们稍微改下,看看另外一个

Channel 是什么?相关推荐

  1. Go 知识点(08) — 对未初始化的 channel 进行读写操作

    1. 对未初始化的 channel 进行写操作 先看下面代码 func main() {var ch chan int // 只声明,并没有初始化fmt.Printf("ch is %v\n ...

  2. Go 知识点(03)— 非缓冲 channel 的长度始终为 0

    我们先看下面代码输出通道的长度是多少? func main() {ch := make(chan string)go func() {ch <- "hello"close(c ...

  3. Go 学习笔记(25)— 并发(04)[有缓冲/无缓冲通道、WaitGroup 协程同步、select 多路监听通道、close 关闭通道、channel 传参或作为结构体成员]

    1. 无缓冲的通道 无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道. 这种类型的通道要求发送 goroutine 和接收 goroutine 同时准备好,才能 ...

  4. Go 分布式学习利器(20)-- Go并发编程之多路选择和超时控制,channel的关闭和广播

    Select 多路选择 基本使用语法如下: select {case ret := <-retCh1: //阻塞事件,等待channel1的消息t.Logf("result %s \n ...

  5. Java NIO系列教程(二) Channel

    为什么80%的码农都做不了架构师?>>>    Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写 ...

  6. Go语言的Channel文章,整个人都感觉不好了

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. Go的Channel是一个很强大的并发数据模型,在一个发送者和多个消费者情况下工作得最好,但是如果是多个发送者,那么在C ...

  7. Netty Channel源码分析

    原文:https://wangwei.one/posts/netty-channel-source-analyse.html 前面,我们大致了解了Netty中的几个核心组件.今天我们就来先来介绍Net ...

  8. POJ-1129 Channel Allocation DFS搜索

    题意:给定一张图,现在对这张图进行染色,且相邻的两个点的颜色不能够相同,问最少要用多少种颜色? 思路:有一下贪心思路,对于没一个节点,我们对其周围的结点进行遍历,对有颜色的邻节点的颜色进行统计,选取一 ...

  9. go channel 缓冲区最大限制_GO语言圣经学习笔记(八)Goroutines和Channels

    奋斗鸭!Day97 知识点 goroutinue 基本用法 golang非常深度的简化了goroutinue的使用方法,异常简单,门槛降低很多 // goroutinue 使用非常简单go f() G ...

  10. mysql多个字符串连接池_使用Coroutine\Channel实现一个简单的MySQL连接池

    Channel通道,类似于go语言的chan,支持多生产者协程和多消费者协程,Swoole底层自动实现了协程的切换和调度 Channel实现原理 通道与PHP的Array类似,仅占用内存,没有其他额外 ...

最新文章

  1. 一、【用django2.0来开发】 环境部署和初始化项目
  2. [转][探讨]为什么说JavaScript是性价比最高的技术?
  3. ibatis常用的集中判断语句
  4. php sha1漏洞,PHP sha1()函数
  5. 加州大学黑科技:激光使电子设备不再依赖半导体材料
  6. 禹洲:我们这一代人的困惑
  7. C# Windows 服务
  8. 网络安全及包分析实验报告
  9. SQL常用脚本大全,建议收藏!
  10. 【渝粤教育】广东开放大学 企业财务报表分析 形成性考核 (26)
  11. 从命令行编译 JScript 代码
  12. 华为开放亚太首个OpenDaylight实验室――被纳入OpenDaylight官方Community Labs 获高度肯定
  13. 正则函数--search/match/findall/sub/split
  14. VMware Tools 启动脚本未能在虚拟机中成功运行。如果您在此虚拟机中配置了自定义启动脚本,请确保该脚本没有错误。您也可以提交支持请求,报告此问题。
  15. 简直无敌!反向代理、负载均衡实战,架构师必备!
  16. 猿创征文|OpenCV 如何提高条形码识别率
  17. 怎样清除浏览器缓存?
  18. Java后端--67--Springboot的响应式编程
  19. java poi 2013,POI读取Excel2013
  20. TUSB3410驱动

热门文章

  1. matlab fgetc,C语言fgetc和fputc函数用法详解(以字符形式读写文件)
  2. sim7600ce 拨号上网测试_SIM7600CE应用程序调试流程
  3. 薛之谦丨当初不以他盛名而来,如今也不会因为诋毁而离开
  4. SpringBoot整合MongoDB实现ResultFul风格接口
  5. pyttsx3设置男性声音
  6. 面试:JavaScript基础概念
  7. 三思助力柬埔寨首条高速开通,再度点亮一带一路重大工程
  8. 文本转语音-微软Azure-一步一步教你从注册到使用
  9. 小白入门python教程自学python
  10. 用python把微信好友头像拼成一张图