多线程

  1. 多线程的应用 主要用于耗时的操作

(1)   耗时操作,例如网络图片、视频、歌曲、书籍等资源下载

(2)   游戏中的声音播放

  1. 多线程基本概念

(1)   每一个程序都有一个主线程,程序启动时创建(调用main来启动)

(2)   主线程的生命周期是和应用程序绑定的,程序退出(结束)时,主线程也就停止了

(3)   多线程技术表示,一个应用程序有多个线程,使用多线程能提供CPU的使用率,防止主线程堵塞

(4)   任何有可能堵塞主线程的任务不要在主线程执行(访问网络)

  1. 程序是计算机指令的集合,它以文件的形式存储在磁盘上。
  2. 每一个进程启动之后,会有一个主线程,遇到耗时的操作时,新建线程去执行可以保证主线程的流畅,新建线程本身会消耗系统资源 线程之间要控制执行顺序相对比较复杂。

进程与线程概念

(1)   进程:是一个程序在其自身的地址空间中的一次执行活动。

  • 进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;
  • 而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。

(2)   线程:是进程中的一个单一的连续控制流程。一个进程可以拥有多个线程。

  • 线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。

(3)   一个运行的程序就是一个进程或者叫做一个任务

(4)   一个进程至少包含一个线程,线程是程序的执行流

(5)   iOS程序启动时,在创建一个进程的同时, 会开始运行一个线程,该线程被称为主线程

(6)   主线程是其他线程最终的父线程,所有界面的显示操作必须在主线程进行!!!

(7)   后台线程无法更新UI界面和响应用户点击事件

(8)   系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间

(9)   每创建一个新的线程,都会消耗一定内存和CPU时间

(10)    当多个线程对同一个资源出现争夺的时候需要注意线程安全问题

  1. 多线程的优势与难点
  2. 优势
  3. 充分发挥多核处理器优势,将不同线程任务分配给不同的处理器,真正进入“并行运算”状态
  4. 将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好
  5. 当硬件处理器的数量增加,程序会运行更快,而无需做任何调整
  6. NSThread 每个NSThread对象对应一个线程,量级较轻
  7. NSOperation/NSOperationQueue 面向对象的线程技术
  8. GCD —— Grand Central Dispatch 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术
  9. 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。但是就目前而言,iOS的开发者,需要了解三种多线程技术的基本使用过程。因为很多框架技术分别使用了不同多线程技术。
  10. 三种多线程技术的对比

iOS的三种多线程技术

(1)   NSThread:

  •  优点:NSThread 比其他两个轻量级,使用简单
  • 缺点:不能控制线程的执行顺序(需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销)(需要使用start方法,才能启动实例化出来的线程、控制并发线程数、先后顺序困难,例如:下载图片(后台线程) -> 滤镜美化(后台线程) -> 更新UI(主线程)

(2)   NSOperation:

  • 不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上
  • NSOperation是面向对象的

(3)   GCD:

  • Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread
  • NSOperation的高效和强大的技术
  • GCD是基于C语言的
  1. 谁的编号为一,谁就是主线程;[NSThread currentThread] = {number = 1, name = main}
  2. 非主线程,跳到主线程,(根类方法)
  • - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
  1. NSObject多线程方法

(1)   [NSThread currentThread] 可以返回当前运行的线程

  • num = 1 说明是主线程
  • 在任何多线程技术中(NSThread,NSOperation,GCD),均可以使用此方法,查看当前的线程情况。

(2)   新建后台线程,调度任务  对NSThread线程封装

  •  [self performSelectorInBackground:@selector(bigTask) withObject:nil]
  • 使用performSelectorInBackground是可以修改UI的,but强烈不建议如此使用。

(3)   更新界面

  • 使用performSelectorOnMainThread可以返回主线程上执行任务。
  •  提示:NSObject对象均可以调用此方法。

(4)   内存管理

  线程任务要包在@autoreleasepool(自动释放池)中,否则容易引起内存泄露,而且非常难发现。

  1. NSObject的多线程小结

(1)   开启后台执行任务的方法

  •  (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg

(2)   在后台线程中通知主线程执行任务的方法

  •  (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

(3)   获取线程信息

  •  [NSThread currentThread];

(4)   线程休眠(仅适用于开发调试时使用)

  •  [NSThread sleepForTimeInterval:1.0f]