本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址(2013年12月29日更新版)

 


多线程 

技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong
 
多线程的应用 
• 耗时操作,例如网络图片、视频、歌曲、书籍等资源下载 • 游戏中的声音播放
 

 
 
多线程示意图 
• 充分发挥多核处理器的优势,并发(同时执行) 执行任务让系统运行的更快、更流畅

 
进程与线程概念 
•  一个运行的程序就是一个进程或者叫做一个任务 
•  一个进程至少包含一个线程,线程是程序的执行流 
•  iOS程序启动时,在创建一个进程的同时, 会开始运行一个线程,该 线程被称为主线程 
•  主线程是其他线程最终的父线程,所有界面的显示操作必须在主线程 进行    
•  后台线程无法更新UI界面和响应用户点击事件 
•  系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中 
的多个线程则共用进程的内存空间 
•  每创建一个新的线程,都会消耗一定内存和CPU时间 
•  当多个线程对同一个资源出现争夺的时候需要注意线程安全问题 

多线程的优势与难点 
• 优势
–  充分发挥多核处理器优势,将不同线程任务分配给不同的处 
   理器,真正进入“并行运算”状态

–  将耗时、轮询或者并发需求高等任务分配到其他线程执行, 并由主线程负责统一更新界面会使得应用程序更加流畅,用 户体验更好 
–  当硬件处理器的数量增加,程序会运行更快,而无需做任何 调整 
• 难点 
–  共享资源的“争夺” 
–  多线程是为了同步完成多项任务,不是为了提高运行效率, 而是为了通过提高资源使用效率来提高系统的整体性能 

多线程使用注意事项 
• 线程使用不是无节制的– iOS中的主线程的堆栈大小是1M
– 从第二个线程开始都是512KB
– 这些数值不能通过编译器开关或线程API函数更改
• 只有主线程有直接修改UI的能力

iOS的三种多线程技术 

1. NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线
程)
2. 以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去 关心线程的具体使用问题
.1.  NSOperation/NSOperationQueue 面向对象的线程技术 
.2.  GCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多 
     核,是苹果推荐使用的多线程技术
.
以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高 的使用越简单,也是Apple最推荐使用的。但是就目前而言,iOS的开发者, 需要了解三种多线程技术的基本使用过程。因为很多框架技术分别使用 了不同多线程技术。

三种多线程技术的对比 
• NSThread:
–  优点:NSThread 比其他两个轻量级,使用简单 
–  缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以 及唤醒等。线程同步对数据的加锁会有一定的系统开销 
• NSOperation: 
–  不需要关心线程管理,数据同步的事情,可以把精力放在自己需 
要执行的操作上 
–  NSOperation是面向对象的 • GCD: 
–  Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。 iOS4.0+才能使用,是替代NSThread, NSOperation的高效和强大 的技术 
//转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3494799.html
–  GCD是基于C语言的 

演练(1)NSObject的多线程方法——准备 
.1.  创建一个耗时较长的操作 
.2.  创建一个耗时较短的操作 
.3.  在界面中心放置两个按钮,分别调用 这两个任务 
.4.  使用[NSThread currentThread]分别打 印各个任务所在的线程 
.5.  运行观察效果 
•  提示: 
•  NSLog是一个相当耗时的操作 在应用 程序正式发布前,一定记住需要对应用 中的NSLog方法进行处理 
•  无论使用哪一种多线程技术,均可以使 用[NSThread currentThread]查看当前任 务所在线程 
 

 
 
NSObject的多线程方法——后台线程
- (void)performSelectorInBackground:(SEL)aSelector
withObject:(id)arg 
•  通常,由于线程管理相对比较繁琐,而很多耗时的任务又无法知道其准 确的完成时间,因此可以使用performSelectorInBackground方法 直接新建一个后台线程,并将选择器指定的任务在后台线程执行,而无 需关心具体的NSThread对象  
•  提示: 
– performSelectorInBackground方法本身是在主线程中执行的, 
而选择器指定的方法是在后台线程中进行的 
– 使用performSelectorInBackground方法调用的任务可以更新 
UI界面– 在大型交互式游戏中,通常使用此方法在后台线程播放音效  

@autoreleasepool 
• 内存管理对于多线程非常重要
• Objective-C可以凭借@autoreleasepool使用内存资源,并需要时回 收资源
• 每个线程都需要有@autoreleasepool,否则可能会出现内存泄漏 

NSObject的多线程方法——主线程
- (void)performSelectorOnMainThread:(SEL)aSelector
withObject:(id)arg waitUntilDone:(BOOL)wait; 
• 如果要更新UI界面,可以在后台线程中调用
performSelectorOnMainThread方法 
• 提示:尽管使用performSelectorInBackground方法调用的任务 可以更新UI界面,但是在实际开发中,涉及到UI界面的更新操作,还 是要使用performSelectorOnMainThread方法,以避免不必要的 麻烦

NSObject的多线程小结 
• 开启后台执行任务的方法
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
• 在后台线程中通知主线程执行任务的方法– (void)performSelectorOnMainThread:(SEL)aSelector
withObject:(id)arg waitUntilDone:(BOOL)wait; • 获取线程信息
[NSThread currentThread]; • 线程休眠
   [NSThread sleepForTimeInterval:1.0f];
• 特点:– 使用简单,量级轻– 不能控制线程的执行顺序 

NSThread • 创建线程方法: 
1. + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument; 
2. - (id)initWithTarget:(id)target selector: (SEL)selector object:(id)argument; 
• 参数说明:– selector:线程执行的方法,只能有一个参数,不能有返回值 
– target:selector消息发送的对象 – argument:传输给target的唯一参数,也可以是nil

NSThread演练——加载图片 
• detachNewThreadSelector
方法会直接启动线程方法 
• initWithTarget需要调用 start方法才能够启动线程方 法 
 

 
NSOperation & NSOperationQueue
• NSOperation的两个子类1. NSInvocationOperation 2. NSBlockOperation
• 工作原理:

1. 用NSOperation封装要执行的操作
2. 将创建好的NSOperation对象放NSOperationQueue中 
3. 启动OperationQueue开始新的线程执行队列中的操作
• 注意事项:
.1.  使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源, 
    同时运行的线程过多,系统会变慢
.
.2.  使用以下方法可以控制并发的线程数量: 
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 
//转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3494799.html

NSOperation演练——加载图片 
.1.  不能直接使用NSOperation 
.2.  定义完操作后,将添加到操作队列中,即可启动异步操作,否则操 作任务仍然在主线程中执行 
.3.  使用NSBlockOperation更加简单直接 
.4.  使用setMaxConcurrentOperationCount可以限制并发操作数 
量,降低系统开销  
.5.  使用addDependency可以建立操作之间的依赖关系,设定操作的执行 顺序 

 
 
 
 
GCD • GCD是基于C语言的框架
• 工作原理:
–  让程序平行排队的特定任务,根据可用的处理资源,安排它们在 
   任何可用的处理器上执行任务

–  要执行的任务可以是一个函数或者一个block 
–  底层是通过线程实现的,不过程序员可以不必关注实现的细节 
–  GCD中的FIFO队列称为dispatch queue,可以保证先进来的任务先 得到执行 
–  dispatch_notify 可以实现监听一组任务是否完成,完成后得 到通知 
• GCD队列:1. 全局队列:所有添加到主队列中的任务都是并发执行的2. 串行队列:所有添加到串行队列中的任务都是顺序执行的 3. 主队列:所有添加到主队列中的任务都是在主线程中执行的 

获取队列的方法 
• 全局队列(可能会开启多条线程) dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  • 串行队列(只可能会开启一条线程) 
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL); 
• 主队列  dispatch_get_main_queue(); 

GCD任务的执行方式——同步&异步 
• 异步操作 
– dispatch_async 在其他线程执行任务,会开启新的线程  – 异步方法无法确定任务的执行顺序 
• 同步操作– dispatch_sync 在当前在当前线程执行任务,不开启新的线程 
– 同步操作与队列无关 
– 同步方法会依次执行,能够决定任务的执行顺序  – 更新界面UI时,最好使用同步方法 

GCD演练——加载图片 
• GCD的优点:– 充分利用多核– 所有的多线程代码集中在一起,便于维护 – GCD中无需使用@autoreleasepool
– 如果要顺序执行,可以使用dispatch_sync同步方法  – dispatch_async无法确定任务的执行顺序 

单例模型 
• 目的:– 保证在内存中永远只有类的单个实例
• 建立方法:

1. 声明一个静态成员变量,记录唯一实例 
2. 重写allocWithZone方法
allocWithZone方法是对象分配内存空间时,最终会调用的方法, 重写该方法,保证只会分配一个内存空间
3. 建立sharedXXX类方法,便于其他类访问
//转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3494799.html

互斥锁的目的,一次只让一个线程访问资源,从而达到资源的线程安全。

 

在iPhone开发中,通常要尽量避免使用互斥锁! 

多线程演练——卖票 
• 系统预设– 共有30张票可以销售(开发时可以少一些,专注实现) – 售票工作由两个线程并发进行– 没有可出售票据时,线程工作停止– 两个线程的执行时间不同,模拟售票人员效率不同– 使用一个多行文本框公告售票进度(主线程更新UI)
• 线程工作安排– 主线程:负责更新UI
– 线程1:模拟第1名卖票员 – 线程2:模拟第2名卖票员 – 两个线程几乎同时开始卖票


单线程卖票流程图 


多线程卖票示意图 

演练准备——更新UI方法,由主线程调用 

// 1. 取出当前的文本 
NSMutableString *str = [NSMutableString stringWithString: [self.textView text]]; 
// 2. 追加文本 [str appendFormat:@"%@\n", text];
// 3. 设置文本 [self.textView setText:str];
// 4. 选中最末位置,实现自动滚动效果 NSRange range = NSMakeRange(str.length - 1, 1);  [self.textView scrollRangeToVisible:range]; 
//转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3494799.html

卖票演练 
• 资源争夺
–  仅使用单例模式无法解决资源争夺问题 
–  使用互斥锁@synchronized可以保证多个线程不会使用同一代码块,而且比 NSLock具有更好的性能  
–  为了保证属性安全,被争夺资源的属性应该设置为原子属性atomic • GCD 
–  GCD的多线程更加灵活、方便 
–  dispatch_group_notify可以监听一组任务是否完成。这个方法很有用,比如 
    你执行三个下载任务,当三个任务都下载完成后,才通知界面说已经完成

–  如果不需要监听一组任务,可以直接使用dispatch_async方法 
• NSOperation
– 更新界面时使用[[NSOperationQueue 
mainQueue]addOperationWithBlock:方法  • NSThread 
– 涉及到线程调度问题,日常开发不建议使用 


三种多线程技术的流程对比 

关于iOS多线程使用的建议 

• 掌握大纲内容即可,关于多个线程之间的调度问题,待日后熟练后可
以自行学习,目前不建议再继续深入  
• 关于多线程必须记住的三个要点
– 只能在主线程中更新UI
– 共享数据争夺的处理,互斥锁@synchronized(self)和原子属
性atomic
– 不要使用多种多线程技术去争夺同一个资源 
• 使用多线程是为了处理并发操作的。如果有可能,我们不要去做抢资 源的事情 互斥锁的代价相当的昂贵 

 

//转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3494799.html 

https://www.evernote.com/shard/s227/sh/8e2008b3-1d9e-42e6-b193-551e6dbe7440/e39f99e835da159ac641e28679c3c00b

多线程---iOS-Apple苹果官方文档翻译的更多相关文章

  1. iOS数据存取---iOS-Apple苹果官方文档翻译

    CHENYILONG Blog iOS数据存取---iOS-Apple苹果官方文档翻译 数据存取/*技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http:// ...

  2. iOS网络基础---iOS-Apple苹果官方文档翻译

    CHENYILONG Blog iOS网络基础---iOS-Apple苹果官方文档翻译 iOS网络基础 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http: ...

  3. iOS静态库 ---iOS-Apple苹果官方文档翻译

    iOS静态库 ---iOS-Apple苹果官方文档翻译 •什么是库? 库是共享程序代码的方式,一般分为静态库和动态库.静态库与动态库的区别? 静态库:链接时完整地拷贝至可执行文件中,被多次使⽤用就为什 ...

  4. IOS开发苹果官方Sample Code及下载地址

    IOS开发苹果官方Sample Code及下载地址 在线浏览地址:https://developer.apple.com/library/ios/navigation/#section=Resourc ...

  5. CALayer---iOS-Apple苹果官方文档翻译之CALayer

    CHENYILONG Blog CALayer---iOS-Apple苹果官方文档翻译之CALayer CALayer /*技术博客http://www.cnblogs.com/ChenYilong/ ...

  6. UIWebView---iOS-Apple苹果官方文档翻译

    CHENYILONG Blog UIWebView---iOS-Apple苹果官方文档翻译 UIWebView 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博h ...

  7. NSURLSession---iOS-Apple苹果官方文档翻译

    CHENYILONG Blog NSURLSession---iOS-Apple苹果官方文档翻译 NSURLSession 技术博客http://www.cnblogs.com/ChenYilong/ ...

  8. iOS程序启动原理---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  9. UIImagePickerController---iOS-Apple苹果官方文档翻译

    //本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址  //转载请注明出处--本文永久链接:http://www.cnblogs.com ...

随机推荐

  1. 访问方式由http改为https curl:(51)

    系统访问由http变为https,先申请了CA证书,然后win下浏览器访问时没问题的,但是linux下通过curl的方式访问就报错: curl:(51) SSLcertificate subject ...

  2. Jenkins系列-Jenkins忘记密码的修复方法

    找回 admin 用户的密码后,可以登录系统修改其他用户的密码. 1. Jenkins 目录结构 Jenkins 没有使用数据库,所有的信息都保存在 JENKINS_HOME 目录下的文件中.其中 J ...

  3. UML图之协作图

    创建方法: 1,new----collaboration diagram 2,根据序列图按F5转换 增加对象链接(图2-4-4)    (1) 选择Object Link 工具栏按钮. (2) 单击要 ...

  4. cf Round 587

    A.Duff and Weight Lifting(思维) 显然题目中只有一种情况可以合并 2^a+2^a=2^(a+1).我们把给出的mi排序一下,模拟合并操作即可. # include <c ...

  5. Django 2.0 学习(09):Django 静态文件(样式和背景图片)

    应用的定制化:静态文件 首先,在polls目录中创建一个名叫static的目录.Django会在该目录里面查找静态文件,类似于Django在polls/template目录下查找模板文件. Djang ...

  6. asp.net AES加密跟PHP的一致,将加密的2进制byte[]转换为16进制byte[] 的字符串获得

    <?php class AESUtil { public static function encrypt($input, $key) { $size = mcrypt_get_block_siz ...

  7. Select-poll-epoll-简介

    1. Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时变成readable 和 ...

  8. 详解 ES6 Modules

    详解 ES6 Modules 对于新人朋友来说,想要自己去搞定一个ES6开发环境并不是一件容易的事情,因为构建工具的学习本身又是一个非常大的方向,我们需要花费不少的时间才能掌握它. 好在慢慢的开始有大 ...

  9. 【刷题】HDU 4405 Aeroplane chess

    Problem Description Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled fr ...

  10. [APIO2015]巴厘岛的雕塑 贪心+DP+特殊数据优化

    写了好久.... 刚刚调了一个小时各种对拍,,,,最后发现是多写了一个等号,,,,内心拒绝 表示一开始看真的是各种懵逼啊 在偷听到某位大佬说的从高位开始贪心后发现可做 首先考虑小数据(因为可以乱搞) ...