cocoa 处理多个网络请求

场景: 在开发中很多时候在同一个界面中会有多个网络请求,而且要在这几个网络请求成功返回的时候再做下一步操作。


分析

  • 一种是对个网络请求结束后统一操作,在一个界面需要同时请求多种数据。比如列表数据,广告数据等,全部请求到再一起刷新界面。
  • 多个请求顺序执行,下一个请求依赖于上一个请求的结果。

这些要求对于普通的操作是可以做到并发控制和依赖操作。但是对于网络请求这种需要时间的请求来说,效果往往和预期是不一样的。因为网络请求是异步的,并不知道什么时候网络请求。
方案

  • 信号量
  • NSOperationQueue
  • dispatch_group_t

    信号量

    信号量是一个整数,在创建的时候会有一个初始值,这个初始值往往代表我要控制的同时操作的并发数。在操作中,对信号量会有两种操作:信号通知和等待。
    信号通知时,信号量+1,等待时如果信号量大于0,则会将信号量-1。否则,会等待知道信号量大于0.什么时候大于0呢?往往是在之前某个操作结束后,我们发出信号通知,让信号量+1。

  • dispatch_semaphore_create:创建一个信号量

  • dispatch_semaphore_signal:信号通知,即信号量+1
  • dispatch_semaphore_wait:等待,直到信号量大于0时,即可操作,同时将信号量-1
    在使用的时候,往往会创建一个信号量,然后进行多个操作,每次操作都等待信号量大于0再操作,同时信号量-1,操作完将信号量+1.当信号量减小到0,这个时候wait操作会起作用。
    DISPATCH_TIME_FOREVER表示会永远等待,一直等到信号量大于0,也就是有操作完成了,将信号量+1了,这时候才可以结束等待,进行操作,并且将信号量-1,这样新的任务又要等待。
NSOperationQueue

NSOperationQueue只有两种队列,即主队列和并行队列。通过[[NSOperationQueue alloc] init];创建的队列都是并行队列,并且可以将一个或多个NSOperation对象放到队列中去执行,而且是异步执行的,一个NSOperation对象可以通过调用start方法来执行任务,但是默认是同步执行的。则主队列通过[NSOperationQueue mainQueue];获得,而且其中所有NSOperation都会在主线程中执行。

当然也可以利用NSOperationQueue的线程依赖,当某个NSOperation对象依赖于其它NSOperation对象的完成时,就可以通过addDependency方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前NSOperation对象才会开始执行操作。需要先添加依赖关系,再将操作添加到队列中。另外,通过removeDependency方法来删除依赖对象。

dispatch_group_t

可以使用dispatch_group_async函数将多个任务关联到一个dispatch_group和相应的queue中,dispatch_group会并发地同时执行这些任务。而且dispatch_group可以用来阻塞一个线程,直到dispatch_group关联的所有的任务完成执行。有时候必须等待任务完成的结果,然后才能继续后面的处理。

多个请求结束后统一操作,最优方案:

假设我们一个页面需要同时进行多个请求,他们之间倒是不要求顺序关系,但是要求等他们都请求完毕了再进行界面刷新或者其他什么操作。

  • dispatch_group_t
    这里写图片描述

dispatch_group会等和它关联的所有的dispatch_queue_t上的任务都执行完毕才会发出同步信号,dispathc_group_notify的代码块block会被执行。从控制台的打印结构可以看出,如果将上面三个操作改成真实的网络操作后,这个简单的做法会变得无效,因为网络请求需要时间,而线程的执行并不会等待请求完成后才真正算作完成,而是只负责将请求发出去,线程就认为自己的任务算完成了,当三个请求都发送出去,就会执行dispathc_group_notify中的内容,但请求结果返回的时间是不一定的,也就导致界面都刷新了,请求才返回,这就是无效的。
这里写图片描述

notify的作用就是在group中的其他操作全部完成后,再操作自己的内容,所以我们会看到上面事件A、B、C执行之后,才执行事件E。
和dispatch_async相比,当我们调用n次dispatch_group_enter后再调用n次dispatch_group_level时,dispatch_group_notify和dispatch_group_wait会收到同步信号;这个特点使得它非常适合处理异步任务的同步当异步任务开始前调用dispatch_group_enter异步任务结束后调用dispatch_group_leve;

  • dispatch_semaphore_t
    这里写图片描述
    在每个请求开始之前,我们创建一个信号量,初始为0,在请求操作之后,我们设一个dispatch_semaphore_wait,在请求到结果之后,再将信号量+1,也即是dispatch_semaphore_signal。这样做的目的是保证在请求结果没有返回之前,一直让线程等待在那里,这样一个线程的任务一直在等待,就不会算作完成,notify的内容也就不会执行了,直到每个请求的结果都返回了,线程任务才能够结束,这时候notify也才能够执行。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值