天天看点

20160823关于GCD与NSOperation的一些比较

关于多线程操作,大部分开发者会采取GCD实现,的确GCD有它强大的地方,但是在执行后台操作的时候,GCD并不是最佳的方式,苹果封装的推出的一种技术NSOperationQueue,本文不是介绍它的使用,而是更多的是一种比较。

一.NSOperationQueue与NSOperation

我们将操作封装在NSOPeration对象中去

将NSOperation对象加入到NSOperationQueue中

系统会⾃动将NSOperationQueue中的NSOperation取出来

将取出的NSOperation封装的操作放到⼀条新线程中执⾏

NSOperation是个抽象类,她有两个子类NSInvocationOperation和NSBlockOperation

二.Compare

GCD是纯C的API,在GCD中任务用块来表示,块是一个轻量级的数据结构,操作(Operation)是个重量级的对象,有时候采用对象带来的开销微乎其微,而带来的好处却很多。使用NSOperationQueue有如下一些好处。

①取消某个操作。如果使用操作的队列,取消操作比较方便,调用cancel方法,而GCD的架构一旦启动就很难取消了,GCD的架构是fire and forget

②指定操作间的依赖关系。可以指定一个操作完成,执行下一个操作,另一种说法是使特定的操作必须在另外一个操作顺利完成后方可执行。

③指定操作的优先级。

④可以通过键值观测机制监控NSOperation对象的属性。

⑤重用NSOperation对象,可以自己写一个类继承NSOperation,扩展性比较好。

总结:在解决多线程与任务管理问题时派发队列并非是唯一的方案。操作队列提供一套高层OC API,能实现GCD绝大部分的功能,而且能完成一些更为复杂的操作。

问题:在开发中是不是会遇到这样的问题,有些操作必须在某些操作完成之后执行?比如下载后续操作必须在下载完成之后操作。

尝试:通过DispatchGroup机制,根据系统资源的状况来执行任务。

dispatchGroup是GCD的一项特性,能够把任务分组,调用者可以等待这组任务执行完毕,也可以在提供回调函数之后继续往下执行,这组任务完成时,调用者会得到通知。其中有个重要的特性,就是把将要执行的多个任务合为一组,合为一组哦,当这组任务完成时,会收到一个通知哦。

下面是一段代码实现上面描述的问题:

可以参考下面一段代码

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    
    //do some object perform Task
    for (id object in <#collection#>) {
        dispatch_group_async(dispatchGroup, queue, ^{
            //object perform tasks
        });
    }
    dispatch_queue_t notifyQueue = dispatch_get_main_queue();
    dispatch_group_notify(dispatchGroup, notifyQueue, ^{
        //continue processing after completing tasks
    });
           

或许下面一段代码更加容易理解

dispatch_queue_t dispatchQueue = dispatch_queue_create("sw.queue...", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dispatch-1");
    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dspatch-2");
    });
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    });
           

对比上面的两段代码,原理是一样的。

第一段代码我们会遍历某个collection,并在其每个元素上执行任务,而这个操作可以用另一个GCD函数来实现。

void dispatch_apply(size_t iterations, dispatch_queue_t queue, ^(size_t)block)
           

有兴趣可以研究下。

总结:一系列任务可归入一个dispatch group 之中,开发者可以在这组任务执行完毕时获得通知,通过dispatch group,可以在并发式派发队列里同时执行多项任务。此时GCD会根据系统资源状况来调度这些并发执行的任务。

本文 

      完!

继续阅读