1

本文仅作为个人学习总结记录使用!能力有限,难免会有疏漏和错误,还望指出。共同进步。

独白

工作学习IOS已经有半年了,一直都想抽出时间记录一下自己的学习和工作经验,但都写到一半,就没有然后了。关于并发编程,其实国外国内已经有各种牛人总结过非常棒的文章,但大多都是碎片化的文章。我就个人感受而言,总结一下并发编程以及相关的一些知识。

遇到的问题

关于并发编程,大部分的教程要么是直接介绍GCD(Grand Central Dispatch
),要么就是上一大堆的Operation Queues,还有介绍Threads来完成并发。

  • 其实他们都能实现并发,但他们之间有什么区别呢?又有什么联系呢?
  • block和GCD的区别?
  • 关于delegate和block的使用

OS X和iOS中的并发编程

在移动和桌面操作系统中,苹果提供了相同的并发编程API。 常用的分别是:pthread和NSThread,Grand Central Dispatch(GCD)以及NSOperationQueue
由于高层API是基于底层API构建的,所以首先将从底层的API开始介绍,然后逐步介绍高层API,不过在具体编程中,选择API的顺序刚好相反:因为大多数情况下,选择高层的API不仅可以完成底层API能完成的任务,而且能够让并发模型变得简单。

Threads
线程(thread)是组成进程的子单元,操作系统的调度器可以对线程进行单独的调度。实际上,所有的并发编程API都是构建于线程之上的——包括GCD和操作队列(operation queues)。

一般在工作中,都不会使用pthread和NSThread,因为使用pthread或NSThread会引发一个问题:你创建了8个线程,然后在这些线程中调用了框架代码,这些代码也创建了同样的线程(其实它并不知道你已经创建好线程了),这样会很快产生成千上万个线程,最终导致你的程序被终止执行——线程实际上并不是免费的咖啡,每个线程的创建都会消耗一些内容,以及相关的内核资源
基于队列的并发编程API:GCD和operation queue。它们通过集中管理一个线程池(被没一个任务协同使用),来解决上面遇到的问题

Grand Central Dispatch
通过GCD,开发者不用再直接跟线程打交道了,只需要向队列中添加block代码即可,GCD在后端管理着一个线程池。GCD不仅决定着哪个线程(block)将被执行,它还根据可用的系统资源对线程池中的线程进行管理——这样可以不通过开发者来集中管理线程,缓解大量线程的创建,做到了让开发者远离线程的管理。
更多GCD的使用请参考:Low-Level Concurrency APIs

Operation Queues
操作队列(operation queue)是基于GCD封装的一个队列模型。GCD提供了更加底层的控制,而操作队列在GCD之上实现了一些方便的功能,这些功能对于开发者来说会更好、更安全。
关于Operation Queues比较好的文章:Common Background Practices

NSObject
如果你只想让一些代码在后台执行,NSObject也提供了方法。这些方法的名字中都有“performSelector:”,最简单的就是“performSelectorInBackground:withObject:”,它能在后台执行一个方法。它通过创建一个线程来运行方法。定义这些方法必须遵循一下限制:

  • 这些方法运行在各自的线程里,因此你必须为这些Cocoa对象创建一个自动释放池,而主动释放池是与主线程相关的。(arc,请无视)

  • 这些方法不能有返回值,并且要么没有参数,要么只能有一个参数。换句话说,你只能使用以下代码格式中的一种。

  1. -(void)myMethod;
  2. -(void)myMethod:(id)myObject;

记住这些限制,我们实现的代码应该如下所示:

-(void)myBackgroudMethod{
   @autoreleasepool{
   //todo
   }
}

-(void)myOtherBackgroudMethod:(id)myObject{
   @autoreleasepool{
   // TODO
   }
}

同时调用的时候,应该像这样。

[self performSelectorInBackground:@selector(myBackgroudMethod) withObject:nil];

[self performSelectorInBackground:@ selector(myOtherBackgroudMethod:)  withObject: myObject];

这样就完成了。当方法执行结束后,OC运行时会特地清理并弃掉线程。需要注意,方法执行结束后并不会通知你:这是比较简单的代码

配合NSObject的

performSelectorOnMainThread

也能达到GCD的效果:

-(void)myOtherBackgroudMethod:(id)myObject{
   @autoreleasepool{
   // TODO
    [self performSelectorOnMainThread:@selector(updateUI:) withObject:obj waitUntilDone:YES];
   }
}

-(void)updateUI:(NSObject *)obj{
    // TODO
}

关于block

个人认为比较好的文章:
初识block:
Block剧终:Objective-C中的闭包性和匿名函数:

关于GCD和block之间的区别

Gcd说到底其实就是方便操作线程的一个开源库,并使用了block当做参数来传递这一特性。
Block其实就是OC的匿名函数,并具有闭包的特性,而且可以很容易的获取上下文的信息。和gcd有着本质的区别

总结

以上都是我学习中的总结和注释而已。篇幅不多,大多都是站在别人的肩膀上。主要是给自己回顾和完善知识体系用的。如果有不对的地方,欢迎指出。

参考文章:Concurrent Programming: APIs and Challenges


真烦人
502 声望22 粉丝

吾日三省吾身-为人谋而不忠乎?与朋友交而不信乎?传不习乎?