前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Kotlin 协程】Channel 通道 ② ( Channel 通道容量 | Channel 通道迭代 | 使用 iterator 迭代器进行迭代 | 使用 for in 循环进行迭代 )

【Kotlin 协程】Channel 通道 ② ( Channel 通道容量 | Channel 通道迭代 | 使用 iterator 迭代器进行迭代 | 使用 for in 循环进行迭代 )

作者头像
韩曙亮
发布2023-03-30 18:32:31
6850
发布2023-03-30 18:32:31
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、Channel 通道容量


Channel 通道 其 本质是一个 先进先出 队列 ;

Channel 通道 中维护了一个 缓冲区 , 该缓冲区有一定的 容量 ;

调用 Channel#send 函数 , 会 向缓冲区中发送数据 ,

调用 Channel#receive 函数 , 会从缓冲区中抽取数据 ,

如果 缓冲区 数据满了 , 则 Channel#send 函数就会挂起 ,

直到 调用 Channel#receive 函数 取走了缓冲区中的数据 , 缓冲区 有了空间 , Channel#send 函数才会恢复执行 ;

代码示例 : 产生数据的频率是 1 秒一个 , 消费数据的频率是 2 秒一个 , 那么需要等待数据消费后 也就是 2 秒 才能消费一个数据 , 产生数据后 1 秒是处于挂起状态的 ;

代码语言:javascript
复制
package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            runBlocking {
                // Channel 通道, 传递 Int 类型数据
                val channel = Channel<Int>()

                // 数据生产者协程
                val producer = GlobalScope.launch {
                    for (i in 0..3) {
                        delay(1000)
                        channel.send(i)
                        println("向通道中发送数据 $i")
                    }
                }

                // 数据消费者协程
                val consumer = GlobalScope.launch {
                    while (true) {
                        delay(2000)
                        val num = channel.receive()
                        println("从通道中获取数据 $num")
                    }
                }
            }
        }
    }
}

执行结果 :

代码语言:javascript
复制
21:35:47.097 System.out   kim.hsl.coroutine     I  从通道中获取数据 0
21:35:47.098 System.out   kim.hsl.coroutine     I  向通道中发送数据 0
21:35:49.137 System.out   kim.hsl.coroutine     I  从通道中获取数据 1
21:35:49.137 System.out   kim.hsl.coroutine     I  向通道中发送数据 1
21:35:51.177 System.out   kim.hsl.coroutine     I  从通道中获取数据 2
21:35:51.178 System.out   kim.hsl.coroutine     I  向通道中发送数据 2
21:35:53.218 System.out   kim.hsl.coroutine     I  从通道中获取数据 3
21:35:53.219 System.out   kim.hsl.coroutine     I  向通道中发送数据 3
在这里插入图片描述
在这里插入图片描述

二、Channel 通道迭代


Channel 通道 其 本质是一个 先进先出 队列 ;

1、使用 iterator 迭代器进行迭代

可以使用 Channel#iterator 对 Channel 通道 进行 迭代 ;

首先 , 调用 channel.iterator() 获取迭代器 ;

然后 , 调用 iterator.hasNext() 检查是否有下一个元素 ,

最后 , 调用 iterator.next() 获取下一个元素 ;

核心代码如下 :

代码语言:javascript
复制
val iterator = channel.iterator()
while (iterator.hasNext()) {
    delay(1000)
    val num = iterator.next()
    println("从通道中获取数据 $num")
}

完整代码示例 :

代码语言:javascript
复制
package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            runBlocking {
                // Channel 通道, 缓冲区大小无限大
                val channel = Channel<Int>(Channel.UNLIMITED)

                // 数据生产者协程
                val producer = GlobalScope.launch {
                    for (i in 0..3) {
                        channel.send(i)
                        println("向通道中发送数据 $i")
                    }
                }

                // 数据消费者协程
                val consumer = GlobalScope.launch {
                    while (true) {
                        val iterator = channel.iterator()
                        while (iterator.hasNext()) {
                            delay(1000)
                            val num = iterator.next()
                            println("从通道中获取数据 $num")
                        }
                    }
                }
            }
        }
    }
}

执行结果 :

代码语言:javascript
复制
21:48:02.741 System.out   kim.hsl.coroutine     I  向通道中发送数据 0
21:48:02.741 System.out   kim.hsl.coroutine     I  向通道中发送数据 1
21:48:02.742 System.out   kim.hsl.coroutine     I  向通道中发送数据 2
21:48:02.743 System.out   kim.hsl.coroutine     I  向通道中发送数据 3
21:48:02.778 OpenG...erer kim.hsl.coroutine     D  Skia GL Pipeline
21:48:03.770 System.out   kim.hsl.coroutine     I  从通道中获取数据 0
21:48:04.808 System.out   kim.hsl.coroutine     I  从通道中获取数据 1
21:48:05.847 System.out   kim.hsl.coroutine     I  从通道中获取数据 2
21:48:06.887 System.out   kim.hsl.coroutine     I  从通道中获取数据 3
在这里插入图片描述
在这里插入图片描述

2、使用 for in 循环进行迭代

使用 for in 循环 对 Channel 通道进行迭代 , 核心代码如下 :

代码语言:javascript
复制
for(num in channel) {
    delay(1000)
    println("从通道中获取数据 $num")
}

代码示例 :

代码语言:javascript
复制
package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            runBlocking {
                // Channel 通道, 缓冲区大小无限大
                val channel = Channel<Int>(Channel.UNLIMITED)

                // 数据生产者协程
                val producer = GlobalScope.launch {
                    for (i in 0..3) {
                        channel.send(i)
                        println("向通道中发送数据 $i")
                    }
                }

                // 数据消费者协程
                val consumer = GlobalScope.launch {
                    while (true) {
                        for(num in channel) {
                            delay(1000)
                            println("从通道中获取数据 $num")
                        }
                    }
                }
            }
        }
    }
}

执行结果 :

代码语言:javascript
复制
21:48:02.741 System.out   kim.hsl.coroutine     I  向通道中发送数据 0
21:48:02.741 System.out   kim.hsl.coroutine     I  向通道中发送数据 1
21:48:02.742 System.out   kim.hsl.coroutine     I  向通道中发送数据 2
21:48:02.743 System.out   kim.hsl.coroutine     I  向通道中发送数据 3
21:48:02.778 OpenG...erer kim.hsl.coroutine     D  Skia GL Pipeline
21:48:03.770 System.out   kim.hsl.coroutine     I  从通道中获取数据 0
21:48:04.808 System.out   kim.hsl.coroutine     I  从通道中获取数据 1
21:48:05.847 System.out   kim.hsl.coroutine     I  从通道中获取数据 2
21:48:06.887 System.out   kim.hsl.coroutine     I  从通道中获取数据 3
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Channel 通道容量
  • 二、Channel 通道迭代
    • 1、使用 iterator 迭代器进行迭代
      • 2、使用 for in 循环进行迭代
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档