【Kotlin】select简介

server/2024/9/23 2:56:39/

1 前言

        协程的 select 是一种用于异步操作的选择器,它允许同时等待多个挂起函数的结果,并在其中一个完成时执行相应的操作。

        能够被 select 的事件都是 SelectClause,在 select.kt 中有定义,如下。

public interface SelectBuilder<in R> {public operator fun SelectClause0.invoke(block: suspend () -> R)public operator fun <Q> SelectClause1<Q>.invoke(block: suspend (Q) -> R)public operator fun <P, Q> SelectClause2<P, Q>.invoke(param: P, block: suspend (Q) -> R)public operator fun <P, Q> SelectClause2<P?, Q>.invoke(block: suspend (Q) -> R): Unit = invoke(null, block)...
}public interface SelectClause0 {public fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R)
}public interface SelectClause1<out Q> {public fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (Q) -> R)
}public interface SelectClause2<in P, out Q> {public fun <R> registerSelectClause2(select: SelectInstance<R>, param: P, block: suspend (Q) -> R)
}internal class SelectBuilderImpl<in R>(private val uCont: Continuation<R>
) : LockFreeLinkedListHead(), SelectBuilder<R>,SelectInstance<R>, Continuation<R>, CoroutineStackFrame
{override fun SelectClause0.invoke(block: suspend () -> R) {registerSelectClause0(this@SelectBuilderImpl, block)}override fun <Q> SelectClause1<Q>.invoke(block: suspend (Q) -> R) {registerSelectClause1(this@SelectBuilderImpl, block)}override fun <P, Q> SelectClause2<P, Q>.invoke(param: P, block: suspend (Q) -> R) {registerSelectClause2(this@SelectBuilderImpl, param, block)}
}

2 select 在 Job 中的应用

         1)应用

fun main() {CoroutineScope(Dispatchers.Default).launch {var job1 = launchJob("job-1", 100)var job2 = launchJob("job-2", 200)var res = select {job1.onJoin { "select: 1" }job2.onJoin { "select: 2" }}println(res) // 打印: select: 1}Thread.sleep(1000) // 阻塞当前线程, 避免程序过早结束, 协程提前取消
}suspend fun launchJob(tag: String, delayTime: Long): Job =CoroutineScope(Dispatchers.Default).launch {println("tag")delay(delayTime)}

        打印如下。

tag
tag
select: 1

        2)onJoin 源码

        onJoin 是 Job 中定义的属性。

public val onJoin: SelectClause0

        说明:在调用 job1.onJoin { xxx } 时,等价于调用了 SelectClause0.invoke 函数,也等价于调用了 SelectClause0.registerSelectClause0 函数。

3 select 在 Deferred 中的应用

        1)应用

fun main() {CoroutineScope(Dispatchers.Default).launch {var task1 = asyncTask("task-1", 100)var task2 = asyncTask("task-2", 200)var res = select {task1.onAwait { "select: $it" }task2.onAwait { "select: $it" }}println(res) // 打印: select: task-1}Thread.sleep(1000) // 阻塞当前线程, 避免程序过早结束, 协程提前取消
}suspend fun asyncTask(tag: String, delayTime: Long): Deferred<String> =CoroutineScope(Dispatchers.Default).async {delay(delayTime)tag}

        打印如下。

select: task-1

        2)onAwait 源码

        onAwait 是 Deferred 中定义的属性。

public val onAwait: SelectClause1<T>

        说明:在调用 task1.onAwait { xxx } 时,等价于调用了 SelectClause1.invoke 函数,也等价于调用了 SelectClause1.registerSelectClause1 函数。

4 selectChannel 中的应用

4.1 onSend

        1)应用

fun main() {var channels = List(2) { Channel<String>() }CoroutineScope(Dispatchers.Default).launch {var res = select {channels[0].onSend("select-1") { "task-1" }channels[1].onSend("select-2") { "task-2" }}println("res=$res") // 打印: res=task-2}receiveTask(200, channels[0])receiveTask(100, channels[1])Thread.sleep(1000) // 阻塞当前线程, 避免程序过早结束, 协程提前取消
}fun receiveTask(delayTime: Long, channel: Channel<String>) {CoroutineScope(Dispatchers.Default).launch {delay(delayTime)var element = channel.receive()println("receive: $element")}
}

        打印如下。

receive: select-2
res=task-2

        2)onSend 源码

        onSendChannel 中定义的属性。

public val onSend: SelectClause1<E>

        说明:在调用 channels[0].onSend(xxx) { yyy } 时,等价于调用了 SelectClause2.invoke 函数,也等价于调用了 SelectClause2.registerSelectClause2 函数。

4.2 onReceive

        1)应用

fun main() {var channels = List(2) { Channel<String>() }sendTask("task-1", 200, channels[0])sendTask("task-2", 100, channels[1])CoroutineScope(Dispatchers.Default).launch {var res = select {channels[0].onReceive { "select: $it" }channels[1].onReceive { "select: $it" }}println(res) // 打印: select: task-2}Thread.sleep(1000) // 阻塞当前线程, 避免程序过早结束, 协程提前取消
}fun sendTask(tag: String, delayTime: Long, channel: Channel<String>) {CoroutineScope(Dispatchers.Default).launch {delay(delayTime)channel.send(tag)}
}

        打印如下。

select: task-2

        2)onReceive 源码

        onReceiveChannel 中定义的属性。

public val onReceive: SelectClause1<E>

        说明:在调用 channels[0].onReceive { xxx } 时,等价于调用了 SelectClause1.invoke 函数,也等价于调用了 SelectClause1.registerSelectClause1 函数。


http://www.ppmy.cn/server/28989.html

相关文章

java设计模式-生成器模式

文章目录 生成器模式&#xff08;Builder&#xff09;1、目的和适用场景2、角色和职责3、实现步骤4、示例15、示例26、优点7、示例场景 生成器模式&#xff08;Builder&#xff09; 生成器模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它用于…

K8s: 应用项目部署运维环境搭建

使用 StatefulSet 部署 Mysql 数据库环境准备是应用的前置准备工作 先在 node 节点上安装 mysql $ sudo yum install mysql-server -y 安装$ sudo systemctl start mysqld 启动$ sudo systemctl enable mysqld 设置开启启动$ sudo mysql_secure_installation 设置安全选项$ my…

基于免疫粒子群算法的考虑负荷需求相应的热电联供系统优化调度(MATLAB实现)

1.研究背景 随着“双碳”战略的提出&#xff0c;各种分布式能源的开发和利用收到越来越多的重视。冷热电联供(Combined Cooling Heating and Power, CCHP)系统在发电的同时可以将燃气轮机产生的废热用于制热或制冷&#xff0c;实现能量的梯级利用&#xff0c;并减少系统的污染气…

使用jdbc方式操作ClickHouse

1、创建测试表&#xff0c;和插入测试数据 create table t_order01(id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime ) engine MergeTreepartition by toYYYYMMDD(create_time)primary key (id)order by (id,sku_id);insert into t_order01 values …

【webrtc】MessageHandler 9: 基于线程的消息处理:执行Port销毁自己

Port::Port 构造的时候,就触发了一个异步操作,但是这个操作是要在 thread 里执行的,因此要通过post 消息 MSG_DESTROY_IF_DEAD 到thread跑:port的创建并米有要求在thread中 但是port的析构却在thread里 这是为啥呢?

【右一的实操记录】全导航,持续更新...

文章目录 &#x1f4da;大数据管理与分析【实验】&#x1f4da;数据结构【实验】&#x1f4da;机器学习【实验】&#x1f4da;大数据安全【实验】&#x1f4da;信息检索【实验】&#x1f4da;爬虫【小实践】&#x1f4da;AIGC&#x1f4da;杂货铺 大部分是和电子笔记对应的实验…

【研发管理】产品经理知识体系-产品设计与开发工具

导读&#xff1a;产品设计与开发工具的重要性体现在多个方面&#xff0c;它们对于产品的成功开发、质量提升以及市场竞争力都具有至关重要的影响。产品设计工具可以帮助设计师更高效地创建和优化产品原型。开发工具在产品开发过程中发挥着至关重要的作用。产品设计与开发工具还…

2023 广东省大学生程序设计竞赛(部分题解)

目录 A - Programming Contest B - Base Station Construction C - Trading D - New Houses E - New but Nostalgic Problem I - Path Planning K - Peg Solitaire A - Programming Contest 签到题&#xff1a;直接模拟 直接按照题目意思模拟即可&#xff0c;为了好去…