Kotlin协程实现多线程异步执行到同步获取结果

使用场景

  • 一个刷新操作需要2个网络请求才能完成刷新
  • 需要查询两次数据库才能刷新界面
  • 需要从两个硬件设备, 比如2个Camera, 读取两帧, 才能开始下一步的操作

非协程的方式, Java也具有这种方式

    @Test
    fun test_CompletableFuture() {
        formatSop("test_CompletableFuture")
        val future1 = CompletableFuture.supplyAsync {
            formatSop("launch future1")
            sleep(1000)
            "future1 1000"
        }
        val future2 = CompletableFuture.supplyAsync {
            formatSop("launch future2")
            sleep(2000)
            "future2 2000"
        }
        val future3 = CompletableFuture.supplyAsync {
            formatSop("launch future3")
            sleep(3000)
            "future3 3000"
        }

        val result1 = future1.join()
        formatSop("result1: $result1")
        val result3 = future3.join()
        formatSop("result3: $result3")
        val result2 = future2.join()
        formatSop("result2: $result2")
    }
 
    private fun sleep(timeMillis: Long) {
        Thread.sleep(timeMillis)
    }
 
    private var startSeconds: Long = 0L

    private fun formatSop(msg: String?) {
        if (startSeconds == 0L) {
            startSeconds = System.currentTimeMillis() / 1000
        }
        val date = System.currentTimeMillis() / 1000 - startSeconds
        println("$date: $msg")
    }

输出的日志如下

0: test_CompletableFuture
0: launch future1
0: launch future2
0: launch future3
1: result1: future1 1000
3: result3: future3 3000
3: result2: future2 2000

带result的都会在当前线程打印
带launch的分别对应不同的子线程
join方法会阻塞当前线程, 直到子线程执行完毕, 这样只有当所有子线程执行完毕, 最后一个当前线程的日志才会被打印

协程的方式

    @Test
    fun test_async() {
        formatSop("test_async")
        GlobalScope.launch {
            val job1 = async {
                formatSop("launch job1")
                delay(1000)
                "job1 1000"
            }
            val job2 = async {
                delay(2000)
                "job2 2000"
            }
            val job3 = async {
                delay(3000)
                "job3 3000"
            }
            val result1 = job1.await()
            formatSop("result1: $result1")
            val result3 = job3.await()
            formatSop("result3: $result3")
            val result2 = job2.await()
            formatSop("result2: $result2")

        }
        Thread.sleep(10 * 1000)
    }

  private var startSeconds: Long = 0L

    private fun formatSop(msg: String?) {
        if (startSeconds == 0L) {
            startSeconds = System.currentTimeMillis() / 1000
        }
        val date = System.currentTimeMillis() / 1000 - startSeconds
        println("$date: $msg")
    }

通过async执行异步任务, 然后通过wait获取异步任务的返回结果, 类似的原理和Java的join类似, 在调用wait之前就已经线程开始了, wait的作用只是为了获取协程的执行结果, 获取不到就wait.
上述代码的打印结果如下

0: test_async
0: launch job1
1: result1: job1 1000
3: result3: job3 3000
3: result2: job2 2000

协程Flow的方式

flow让我想起RxJava的一些操作符, 又麻烦又不实用, 平添记忆负担. 对flow的一种使用情况进行测试, 其他情况可能有能够异步执行的方式, 下面方式实际上没有做到多线程异步, 最后还是同步一个个的执行.

  @Test
    fun test_flow() {
        formatSop("test_flow")
        runBlocking<Unit> {
            val flow1 = flow {
                formatSop("launch flow1")
                sleep(1000)
                emit("flow1 1000")
            }
            val flow2 = flow {
                formatSop("launch flow2")
                sleep(2000)
                emit("flow2 2000")
            }
            val flow3 = flow {
                formatSop("launch flow3")
                sleep(3000)
                emit("flow3 3000")
            }

            // 同时启动并等待两个任务完成
            launch {
                flow1.collect { formatSop(it) }
                flow3.collect { formatSop(it) }
                flow2.collect { formatSop(it) }
            }
            launch {
            }
            launch {
            }
        }
    }

    private var startSeconds: Long = 0L

    private fun formatSop(msg: String?) {
        if (startSeconds == 0L) {
            startSeconds = System.currentTimeMillis() / 1000
        }
        val date = System.currentTimeMillis() / 1000 - startSeconds
        println("$date: $msg")
    }

输出

0: test_flow
0: launch flow1
1: flow1 1000
1: launch flow3
4: flow3 3000
4: launch flow2
6: flow2 2000

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值