在iOS开发中,有三种多线程处理方式:
- 利用NSThread
- NSOperation和NSOperationQueue
- 利用GCD(Grand Central Dispatch)
使用上,从1到3是越来越简单,但是,对于1和2还是需要了解一下,了解本质有利于在出现一些bug时思考得更深入一些。
NSThread
iOS和Android一样,只能在UI线程更新UI界面,如果在子线程需要更新UI控件,需要执行[self performSelctrorOnMainThread: withObject: waitUntilDone:]来进行更新操作。
第一次运行输出如下:
第二次运行输出如下:
可以看到,虽然启动了线程,但是不是一启动就进入执行状态,CPU会在线程之间切换执行,线程就会在运行、就绪状态间切换,如需调用start函数后(此时线程处于就绪态)马上切换到运行态,可在主线程调用此函数: [NSThread sleepForTimeInterval:0.001]让线程休眠一下,进入阻塞状态,然后等待CPU调度,如果想让线程有更多的运行机会,可以调整优先级,默认优先级为0.5:
结果如下:
在子线程出现如下情况会自行终止:
- 线程逻辑函数处理完成
- 线程执行中发生异常
- 调用了[NSThread exit]
注意:主线程结束后,由主线程启动的子线程不会跟随终止,可以如下在UI线程终止子线程,利用发生cancle信号:
程序和运行结果如下:
这里设定500毫秒后发送终止子线程信号,子线程判断收到cancel信号后终止自己。
NSOperation和NSOperationQueue
NSOperationQueue是一个FIFO队列,负责管理系统提交的多个NSOperation。
NSOperation类型Java里的Runnable接口,代表一个多线程任务,它有NSInvocationOperation和NSBlockOperation两个子类(用于封装需要异步执行的任务),这两个子类可以直接使用,或者开发者可以自己继承NSOperation来实现自己的子类。
开发步骤:
- 创建NSOperationQueue队列,设置其属性
- 创建NSOperation子类的对象,然后将对象提交到NSOperationQueue队列,队列将按顺序依次启动每个NSOperaion。
示例:
可以看到,这里开启了两个线程来处理任务。
GCD
核心概念:
- 队列:在底层维护一个线程池,使用FIFO方式管理开发者提交的任务,有串行队列和并发队列
- 任务:开发者提交给队列的工作单元,这些任务会交由队列底层的线程池内执行
开发步骤:
- 创建队列
- 将任务提交给队列
示例:
这里创建了一个串行队列和一个并发队列并且都以异步方式提交任务。在输出中可以发现,在串行队列中,会先后执行代码块,而在并发队列中,会并发执行代码块。
另外,还有dispatch_once可以让代码只运行一次,通常用于单例模式,dispatch_apply可以让代码重复运行多次,这里就不进行测试了。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 linjk121@163.com.