warning tip
- GCD中的global并行队列是单例,只是在栅栏队列里由于不知名原因,表现得不是一个队列,但是实际还是一个单例
- 开发中要自定义一个全局队列的话使用正常的单例就可以了
- NSOperation有两个子类,
NSBlockOperation
和NSInvocationOperation
,正常情况它们是这样使用的 - NSBlockOperation
|
|
- NSInvocationOperation
|
|
- 上面的代码并没有主动控制线程,NSInvocationOperation的执行线程都是在主线程中,NSBlockOperation第一个block在主线程中,追加的则在子线程中,一般开发中我们不会这样直接使用,需要配合队列使用
配合队列很简单
NSOperationQueue
|
|
- NSInvocationOperation
|
|
- 上面的都会自动创建多个线程同时进行,所以都是并行队列,如果想要串行执行,就把最大并行数设置为1就可以了
|
|
- NSOperation有个好处就是可以自定义任务
- 创建一个继承自NSOperation的对象
|
|
- 然后.m文件里把想要执行的任务填写在重写的main函数里
|
|
- 自定义NSOperation的操作方法
|
|
NSOperation的暂停、恢复和取消
- NSOperation中还有暂停(suspended),恢复(!suspended)和取消(cancelAllOperations)功能,其实操作很简单,就拿到对应的队列操作就可以了,但是有些注意点
- 如果是一个串行队列,里面有多个任务,当队列设置为取消或者暂停的时候,那么正在执行的任务不会暂停,知道执行结束,下一个任务不会再执行
- 如下面的多个任务
|
|
- 暂停代码
|
|
- 由于暂停受到如此的限制,所以即使苹果也建议我们在自定义的任务中,做耗时操作时,可以分段做出一些判断,当察觉到线程状态改变时,及时主动停止任务
|
|
- 自定义任务只能访问isCancelled属性,在几个耗时代码之间插入判断,当线程被取消时,主动return
线程依赖
- 这里有点类似于GCD中的栅栏,但是它更厉害一些,栅栏的使用必须要在同一队列中,而NSOperation没有这样的限制
- GCD栅栏
|
|
- 上面的栅栏无法起到限制作用,栅栏依然有可能在前面的异步之前执行,因为必须要在同一队列中
- 再来看看NSOperation的
|
|
- 上面的代码无论执行多少次,
op5
都只会在最后执行,并且没有队列限制
线程间的通信
- 知道了怎么添加线程依赖后,就可以来学习线程通信了
- 因为线程通信牵扯到线程的先后执行,只有当耗时操作完成后,才能来通知主线程刷新UI,这就是线程通信
|
|
- 上面的代码没有体现出线程依赖的使用,下面弄个有线程依赖的
|
|
不管怎样,UI的刷新必定在数据下载线程完毕之后
同步在串行队列里造成死锁的情况解析
12345678910111213141516171819202122232425262728293031323334353637383940414243/*1:- (void)viewDidLoad {//dispatch_sync(dispatch_get_main_queue(), ^{//NSLog(@3);//死锁原因//1:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁//2:dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。//});//dispatch_async(dispatch_get_global_queue(), ^{//async 在主线程中 创建了一个异步线程 加入 全局并发队列,async 不会等待block 执行完成,立即返回NSLog(@2);//不会造成死锁;});}分析这段代码:view DidLoad 在主线程中,也即dispatch_get_main_queue()中,执行到sync时向dispatch_get_main_queue()插入同步thread,sync会等到后面的block执行完成才返回。sync又在主队列里面,是个串行队列,sync是后面才加入的,前面一个是主线程,所以sync想执行block必须等待前一个主线程执行完成,而主线程却在等待sync返回,去执行后续工作,从而造成死锁。2:dispatch_sync 和 dispatch_async 区别:dispatch_async(queue,block) async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。dispatch_sync(queue,block) sync 同步队列,dispatch_sync 函数不会立即返回,即阻塞当前线程,等待 block同步执行完成。3:GCD Queue 分为三种:1,The main queue :主队列,主线程就是在个队列中。2,Global queues : 全局并发队列。3,用户队列:是用函数 dispatch_queue_create 创建的自定义队列*/队列是管理任务的,当我们用dispatch_async或者dispatch_sync这些函数加入队列中的时候,只是把任务塞给了队列
- 然后由队列来分配线程执行任务
- 那么async与sync其实指的就是任务的优先级
- 在串行队列中,任务的执行是按顺序的,那么排在最前面的任务优先级最高
- 在并行队列中,任务执行不按顺序
- dispatch_sync本身是一个函数,它执行同时又要执行它的代码块,这些任务都是相同优先级,会对线程资源造成抢占
- 而在dispatch_async没有任务的顺序强制性,所以,不会造成资源抢占