GCD基本使用总结

1.GCD的基本使用

1.1 同步执行 + 串行队列

总结:所有任务都是在主线程完成的,证明了同步执行不具备开启新的线程。所有任务都是按序执行。

1.2 同步执行+并发队列

总结:所有任务都是在主线程中执行的,没有开启新的线程,也就是说同步不具备开启新线程的能力。虽然并发队列可以同时执行多个任务,但是当前只有一个线程,一个线程只能执行一个任务,所以这里也就不存在并发队列。

1.3 异步执行+ 串行队列

特点:开启了一条新线程number=3,异步执行具备开启新线程的能力,串行队列每次只有一个任务被执行,因此也只在一个线程执行任务。

2018-10-12 17:18:22.862107+0800 GCD[3829:341432] asyncConcurrent---begin

2018-10-12 17:18:22.862212+0800 GCD[3829:341432] asyncConcurrent---end

是在主线程上执行的,异步执行不需要任何等待,所以 asyncConcurrent---end提前打印出来。

总结:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务。

1.4 异步执行 + 并发队列

总结:除了主线程,又开启了3个线程,并且任务是交叉进行的。

2018-10-12 17:52:03.674846+0800 GCD[4443:409511] asyncConcurrent---end

执行不需要等待。证明了异步执行不需要等待。

1.5 同步执行 + 主队列

总结:会直接崩溃。这是因为我们在主线程中执行syncMain方法,相当于把syncMain任务放到了主线程的队列中。而同步执行会等待当前队列中的任务执行完毕,才会接着执行。那么当我们把任务1追加到主队列中,任务1就在等待主线程处理完syncMain任务。而syncMain任务需要等待任务1执行完毕,才能接着执行。那么,现在的情况就是syncMain任务和任务1都在等对方执行完毕。这样大家互相等待,所以就卡住了,所以我们的任务执行不了,而且syncMain---end也没有打印。

1.6 异步执行 + 主队列

总结:因为是主队列,所以所有任务都是在主线程中被执行。追加任务不需要等待asyncMain方法执行完就执行自己的任务,说明异步执行不需要任何等待。而且所有追加任务必须是按照顺序执行,因为主队列是串行队列。

2. GCD线程间通信

GCD什么时候用到了线程通信?在iOS开发中,UI刷新,点击等事件全在主线程中进行。把有些耗时操作比如下载等就放在其他线程中,当耗时操作完成了怎么通知主线程呢?而当我们有时候在其他线程完成了耗时操作时,需要回到主线程,那么就用到了线程之间的通讯。

总结:可以看到在其他线程中先执行任务,执行完了之后回到主线程执行主线程的相应操作。

3. GCD的其他方法

3.1 GCD栅栏方法:dispatch_barrier_async

举个例子,需要异步执行几组任务,但是有个前提就是执行完任务1和任务2,才能执行任务3和任务4。dispatch_barrier_async函数会等待前边追加到并发队列中的任务全部执行完毕之后,再将指定的任务追加到该异步队列中。

总结:先执行栅栏前面的操作之后,才执行栅栏操作,最后执行栅栏后边的操作。

3.2 GCD延时执行方法:dispatch_after

这是个延时方法,比如我需要在3秒之后执行某个任务,就用dispatch_after函数来实现。经过实践证明dispatch_after函数并不是在指定时间之后执行任务,而是在指定时间之后将任务异步追加到主队列中。严格来说,这个时间并不是绝对准确的,但想要大致延迟执行任务,dispatch_after函数是很有效的。

3.3 GCD只执行一次:dispatch_once

用在单例上,dispatch_once函数能保证某段代码在程序运行时只被执行1次,在多线程的环境下能保证线程安全。

3.4 GCD遍历方法:dispatch_apply

dispatch_apply按照指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束。举个例子说遍历0-5这6个数字,for循环的做法是每次取出一个元素,逐个遍历。dispatch_apply同时遍历多个数字。写个代码打印看看。

总结:因为是在并发队列中异步队执行任务,所以各个任务的执行时间长短不定,最后结束顺序也不定。但是apply---end一定在最后执行。这是因为dispatch_apply函数会等待全部任务执行完毕。

3.5 GCD的队列组:dispatch_group

有时候我们会有这样的需求:分别异步执行2个耗时任务,然后当2个耗时任务都执行完毕后再回到主线程执行任务。这时候我们可以用到 GCD 的队列组。

dispatch_group_async先把任务放到队列中,然后将队列放入队列组中。

dispatch_group_notify监听group中的任务完成状态,当所有任务完成了,追加任务到group中,并执行任务。

3.6 dispatch_group_wait

当前所有任务执行完之后,才执行 dispatch_group_wait 之后的操作。但是,使用dispatch_group_wait 会阻塞当前线程。

3.7 GCD信号量:dispatch_semaphore

dispatch_semaphore_create:创建一个Semaphore并初始化信号

dispatch_semaphore_signal:发送一个信号,让信号总量加1

dispatch_semaphore_wait:信号量减1

(void)semaphoreSync方法一直在主线程中执行,所以会率先输出

2018-10-13 20:39:39.955607+0800 GCD[16954:1531938] currentThread---<NSThread: 0x60c00006e7c0>{number = 1, name = main}

2018-10-13 20:39:39.955774+0800 GCD[16954:1531938] semaphore---begin

2018-10-13 20:39:39.955948+0800 GCD[16954:1531938] 主线程打印

然后遇到    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 此时信号为0,当前主线程进入等待-阻塞状态。

其次异步任务1开始执行,任务1执行到   dispatch_semaphore_signal(semaphore); 发送总信号,此时信号+1;被阻塞的主线程继续执行任务,最后打印:

2018-10-13 20:39:41.957827+0800 GCD[16954:1531938] semaphore---end,number = 100

我的理解:GCD的同步与异步区别就是----是否开启新的线程,以及线程之间任务之间是否等待

猜你喜欢

转载自blog.csdn.net/ivolcano/article/details/89817117