await多路复用
两个API网络和本地获取数据,期望哪个先返回就用哪个:
// 多路复用,谁先返回使用谁
fun test() = runBlocking {
GlobalScope.launch {
val local = getUserFromLocal("george")
val net = getUserFromNet("george")
val result = select<String> {
local.onAwait{it}
net.onAwait{it}
}
// 最终使用哪个,看哪个先返回
result.let {
Log.d(TAG, "test: $it")
}
}.join()
}
fun CoroutineScope.getUserFromLocal(name:String)=async(Dispatchers.IO) {
delay(300)
"${name}read Local"
}
fun CoroutineScope.getUserFromNet(name:String)=async(Dispatchers.IO) {
delay(200)
"${name}read Net"
}
select会返回最先返回的数据
多路复用channel
fun test2() = runBlocking {
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
Log.d(TAG, "result:$result")
}
flow实现多路复用
fun test3() = runBlocking {
//模拟实现多路复用
//函数->协程->flow->flow合并
val name = "guest"
coroutineScope {
listOf(
async { getUserFromLocal(name).await() }, // 使用async直接执行
async { getUserFromNet(name).await() }
)
.map { deferred -> flow { emit(deferred.await()) } }
.merge() //多个flow合并成一个flow
.collect { user -> //末端操作符
Log.d(TAG,"result:$user")
}
}
}
fun CoroutineScope.getUserFromLocal(name: String) = async(Dispatchers.IO) {
delay(300)
"${name} read Local"
}
fun CoroutineScope.getUserFromNet(name: String) = async(Dispatchers.IO) {
delay(200)
"${name} read Net"
}
两个结果都会通过collect输出,耗时最短的先输出。
Mutex并发安全
// 按照顺序打印出count。如果不使用Mutex,会发现值跳跃(例如:5->7->6)
fun test4(){
runBlocking {
var count = 0
val mutex = Mutex()
List(100){
GlobalScope.launch {
mutex.withLock {
count++
Log.d(TAG,"countAdd:$count")
}
}
}.joinAll()
Log.d(TAG,"count:$count")
}
}
Mutex轻量级锁,lock和unlock,在获取不到锁时不会阻塞线程,而是挂起等待锁的释放。