协程(三)——协程在并发中的优势

本文探讨了协程在处理并发请求时的优势,通过对比RxJava的嵌套实现,展示了协程如何简化并发代码,实现接口同时请求并等待其结果,避免了代码累赘和顺序执行的问题。协程利用suspend关键字实现可挂起函数,以同步方式表达异步操作,提高了代码的可读性和简洁性。
摘要由CSDN通过智能技术生成

上一篇讲了启动协程需要满足的三大条件,同时给出了启动协程的栗子,有兴趣可以去看看,链接如下:

协程(二)——kotlin中协程启动的条件_水很清的博客-CSDN博客

这篇文章讲讲协程在并发中的优势,并发是个复杂的过程,内部机制就不说了,不太懂也说不好,我们来讲讲处理并发的方法就行。

假设现在有这个一个需求,有两个接口,我们需要将两个接口请求后的结果拼接在一起打印出来。

很简单,一般想的都是这样子,先请求接口1,完成后再请求接口2,成功后将两次结果拼接起来打印即可。

我们用Rxjava举个例子:

api.request1()
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe(object:SingleObserver<String>{
       override fun onSuccess(s:String){
           api.request2(s)
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe(object:SingleObserver<String>{
                   override fun onSuccess(ss:String){
                       Log.e(TAG,s+ss)
                   }

                   override fun onSubscribe(d:Disposable){
       
                   }

                   override fun onError(e:Throwable){
       
                   }
            });
       }

       override fun onSubscribe(d:Disposable){
       
       }

       override fun onError(e:Throwable){
       
       }
});

上面的代码可以实现需求,但是能进行了嵌套,代码不美观,设想一下,两个接口做了一次潜套,那如果三个接口呢?四个呢?或者更多呢?代码将十分累赘可读性极差,所以采用嵌套终究不是一个办法。

还有一个问题,现在的做法使接口按照顺序进行了执行,先接口1后再接口2,那如果需要两个接口同时请求呢?不分先后顺序,该如何打印两次请求的拼接结果呢?

我们都知道,接口的请求时间是不定的,而且是在新线程中去执行的,而我们打印是在主线程的,同时请求,我们如何确保在打印的时候,两次请求是已经执行完的呢

针对这个问题,应该会有人做一个延时操作,比如延迟10秒打印,基本可以符合要求,但是做不到万无一失,如果其中某一个接口请求在10秒没执行完呢,那岂不是拿不到接口返回数据呢?所以这种方法也不妥。

还是看看协程的做法吧,先上代码


private val mScope = MainScope()

mScope.launch {
    val job1 = async{
        request1()
    }

    val job1 = async{
        request2()
    }

    Log.e(TAG,${job1.await()}+${job2.await()})
}

//请求接口1的方法
suspend fun request1():String{
 api.request1()
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe(object:SingleObserver<String>{
                   override fun onSuccess(ss:String){
                       
                   }

                   override fun onSubscribe(d:Disposable){
       
                   }

                   override fun onError(e:Throwable){
       
                   }
            });
}

//请求接口1的方法
suspend  fun request2():String{
 api.request2()
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe(object:SingleObserver<String>{
                   override fun onSuccess(ss:String){
                       
                   }

                   override fun onSubscribe(d:Disposable){
       
                   }

                   override fun onError(e:Throwable){
       
                   }
            });
}

上面代码,我们使用了关键字suspend,把request1跟request2申明为可挂起方法,然后使用launch启动一个协程,在launch里面在开启一个子协程,使用了async的方法,然后我们打印的时候在父协程里面的。

所以,Log.e在执行的时候,会去等待,等待request1跟request2请求完成后才打印。而且可以做到request1跟request2是同时进行的,并发的,我们只不过是在他们请求的时候挂起等待,等待请求结束后再打印。

是不是感觉十分的简单,协程的优势立马凸显出来了,不存在像RxJava一样的嵌套,也不用去考虑请求结束的实际,一切都内部帮我们处理好了,我们只需要按照上面代码那么写就行,然后记得在Activity\Fragment销毁的时候cancel协程就行 

mScope.cancel()

 还是之前文章的那句话

协程异步就是将耗时的函数标记为suspend,并在协程中调用!不需要开启新线程,不会阻塞UI。

然后还要再加上一句,用同步的方式去表达异步

例子看上去就像同步一样,但实际上是异步执行,这就是协程的魅力所在。that‘s all 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值