前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android面试题之Kotlin多路复用和并发

Android面试题之Kotlin多路复用和并发

作者头像
AntDream
发布2024-06-13 20:52:57
780
发布2024-06-13 20:52:57
举报
多路复
await 多路复用

两个API分别从网络和本地缓存取数据,期望哪个先返回就先用哪个

代码语言:javascript
复制
private val filePath = "xxx"
private val gson = Gson()

data class Response<T>(val value:T, val isLocal:Boolean)

fun CoroutineScope.getUserFromLocal(name:String) = async(Dispatchers.IO){
    delay(1000)
    File(filePath).readText().let { gson.fromJson(it, User::class.java) }
}

fun CoroutineScope.getUserFromRemote(name:String) = async(Dispatchers.IO){
    userServiceApi.getUser(name)
}

/**
 * @desc: 多路复用和并发
 */
class CoroutineTest5 {

    @Test
    fun `test select` ()= runBlocking<Unit>{
        GlobalScope.launch {
            val localRequest = getUserFromLocal("xxx")
            val remoteRequest = getUserFromRemote("yyy")
            val userResponse = select<Response<User>> {
                localRequest.onAwait{Response(it, true)}
                remoteRequest.onAwait{Response(it, false)}
            }
            userResponse.value?.let { println(it) }
        }.join()

    }
}

select会返回最先返回的Response

多路复用channel
代码语言:javascript
复制
@Test
fun `test select channel` ()= runBlocking<Unit>{
    val channels = listOf(Channel<Int>(), Channel<Int>())
    GlobalScope.launch {
        delay(200)
        channels[0].send(200)
    }
    GlobalScope.launch {
        delay(100)
        channels[1].send(100)
    }
    val result = select<Int?> {
        channels.forEach{channel ->
            channel.onReceive{it}
        }
    }
    //会输出较快的那个,也就是100
    println(result)

}
哪些事件可以被select
  • 能被select的事件都是SelectClauseN类型
  • 要确认挂起函数是否支持select,只需要查看其是否存在对应得SelectClauseN类型可回调即可
flow实现多路复用
代码语言:javascript
复制
//最终2个结果都会输出
@Test
fun `test select flow` ()= runBlocking<Unit>{
    //模拟实现多路复用
    //函数->协程->flow->flow合并
    val name = "guest"
    coroutineScope {
        listOf(::getUserFromLocal, ::getUserFromRemote)
            .map { function-> function.call(name)}//遍历调用
            .map { deferred-> flow { emit(deferred.await()) } }
            .merge()//多个flow合并成一个flow
            .collect { user->//末端操作符
                println("result:$user")
                println("collect")
            }
    }
}
并发安全

协程的并发工具

  • Channel:并发安全的消息通道
  • Mutex:轻量级的锁,它的lock和unlock从语义上和线程锁比较类似,之所以轻量,是因为它在获取不到锁时不会阻塞线程,而是挂起等待锁的释放
  • Semaphore:轻量级信号量,信号量可以有多个,协程在获取到信号量后即可执行并发操作。当semaphore的参数为1时,效果等价于Mutex
代码语言:javascript
复制
```
@Test
fun test safe concurrent tools ()= runBlocking{
    var count = 0
    val mutex = Mutex()
    List(100){
       GlobalScope.launch {
            mutex.withLock {
             count++
           }
       }
    }.joinAll()
    println(count)
}
```

码字不易,求转发,求点在看,求关注,感谢!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AntDream 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 多路复
    • await 多路复用
      • 多路复用channel
        • 哪些事件可以被select
          • flow实现多路复用
          • 并发安全
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档