iOS中并发编程的实现方式及各种方式的比较

iOS中主要有三种实现并发编程的方式,他们分别是GCD、NSOperation和NSThread,接下来,我对这三种实现方式分别进行简介:

1、GCD,全称是Grand Central Dispatch。这是在iOS编程中使用最多的并发编程方式,其核心思想就是将需要并发执行的任务封装到block里,通过把block分发到不同类型的队列里,对不同类型的队列,实现并发执行。GCD是一套C语言级别的并发编程方式,通过调用系统提供的C函数来实现,例如:

// dispatch_get_global_queue是用于获取系统提供的并发队列,
// dispatch_async用于把封装好的block分发到指定的队列里,异步执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // 待执行的任务代码
                });

GCD的优势:GCD是一种非常简单的并发编程方式。把要执行的任务封装到block就行了,然后只需要调用一个C函数,就可以实现并发。大部分情况下,开发者不需要维护自己的队列,只需使用系统提供的队列即可,更加节省了开发时间,提高开发效率。同时,GCD不需要开发者直接跟线程操作接触,所有的并发线程由系统提供并维护,大大简化了多线程管理的工作。系统会根据资源的多少来决定并发线程的数量,不会出现线程数量膨胀过多的情况,使整个App运行效率更高。

GCD的劣势:由于GCD是一种C级别的API,故无法运用面向对象的很多特性。GCD采用block封装执行任务,比较适合小型的任务并发执行,对于一些大型的任务,代码量过大,会导致难以维护的尴尬。GCD没有对任务执行状态监听的机制,一旦分发任务,只能等待任务执行完成。

2、NSOperation,NSOperation的核心是对GCD的一种面向对象封装,故其使用方法跟GCD有些类似。把需要并发执行的任务封装到NSOperation里,然后将NSOperation增加到NSOperationQueue里,来实现并发执行。例如:

    static NSOperationQueue *_wm_imageRequestOperationQueue = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _wm_imageRequestOperationQueue = [[NSOperationQueue alloc] init];
        [_wm_imageRequestOperationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
    });
    NSOperation *operation = [[NSOperation alloc] init];
    [_wm_imageRequestOperationQueue addOperation:operation];

使用NSOperation时,需要注意一下几点:
1)NSOperation必须加入NSOperationQueue才会并发执行,如果直接调用start方法,NSOperation会在当前线程执行。
2)NSOperation必须维护自己的NSOperationQueue,系统只提供对应于主线程的mainQueue,不提供其他形式的队列。
3)所有开发者创建的NSOperationQueue都是并发队列,队列里的任务采用FIFO,但是是并发执行,不能保证任务执行完成的顺序。
4)继承NSOperation时,请把需要执行的任务代码写在main方法中。
5)不能直接调用NSOperation的main方法。

NSOperation的优势:其是一种面向对象的并发编程方式,能够使用面向对象的特性。同时NSOperation有一系列的任务执行状态监听机制,能够很方便的管理任务执行。也不需要直接操作线程,简化开发工作。

NSOperation的劣势:开发者需要维护队列,需要对任务进行面向对象封装,编码起来比较繁琐。没有顺序队列。

3、NSThread,这才是iOS真正线程级别的并发编程。每一个NSThread都是一个线程,其任务都是在次线程下执行的。NSThread主要通过target-selector模式,来实现任务的执行,当启动线程时,在启动的线程中,会执行target的selector,从而完成并发任务。也可以采用继承NSThread,重写main方法的模式来实现任务封装。以下是target-selector模式的实现:

- (void)startload
{
    [NSThread detachNewThreadSelector:@selector(loadingdata)
                             toTarget:self
                           withObject:nil];
}
- (void)loadingdata {
    // 需要并发执行的任务
}

NSThread的优势:开发者自己管理线程,能够控制并发任务执行的线程。也有一系列的执行状态控制,但是部分操作需要开发者自己实现。

NSThread的劣势:编程起来比较复杂,开发者需要自己维护线程,增加开发难度。平时很少使用此API来实现多线程开发。

你可能感兴趣的:(iOS进阶之路)