一 创建及组成
GCD是通过c语言创建的,分为三个模块:
1. 队列(用于任务执行顺序)
2. 任务(我们所想要执行的代码)
3. 函数(将任务添加到队列)
二 队列
队列分为两种:
1. 串行队列:必须等前一个任务执行完后下一个任务才能执行,任务执行完成的顺序是有序的.(串行队列只创建一条线程,所以线程会阻塞)DISPATCH_QUEUE_SERIAL
如图将123任务按顺序添加到串行队列中,执行结果也是按顺序完成,即使1任务比较耗时2任务也要等1任务执行完才能执行再然后执行3任务.执行过程中只有一条线程
2. 并发队列:后面的任务不必等前一个任务执行完后再执行,任务执行完成的顺序是无序的具体和CPU调度有关(并发队列会尽可能多的创建多条线程执行任务,所以不会造成线程阻塞). DISPATCH_QUEUE_CONCURRENT
如图:按顺序将1 2 3任务添加到并发队列中,由于1任务执行时间过长所以最后才执行完成.执行过程中创建了三条线程(注意:并不是每执行一个任务就创建一条线程,当一条线程执行完任务后它可能会重复利用这条线程去执行其他任务)
两种队列都遵循FIFO规则,先进来的先执行
三 函数
同步: dispatch_sync(<#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
异步: dispatch_async(<#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
其他
四 全局队列
苹果系统提供了两个全局队列
1. 全局串行队列: dispatch_get_main_queue() 就是我们的主线程
2.全局并发队列: dispatch_get_global_queue(0, 0) 后面的参数0分别代表默认值,第二个参数用于设置优先级
五 案列
1. 在while循环里添加一个异步执行的全局并发队列,问输出结果是多少?
经过多次点击测试,看到控制台输出了大于5的结果. 由于队列是异步执行的,不会阻塞线程,只要 a<5 在a++执行前while循环就可以执行,while循环里又添加一个a++的任务.也就是说只要a<5就会执行n次a++代码.只有当某一次a++的任务执行完成后并且这次任务执行结果使a>=5的时候while循环才会结束.所以输出后的结果是>=5(因为打印IO流是一步耗时操作,在输出的那一刻有可能某一条a++的任务刚好又结束了所以a输出的结果不一定会是while判断的那个a的值)
如何才能获取最大值的a也就是如何获取最终打印结果呢?
如图:在while循环执行完后,在全局队列里又添加了一个打印a的值的任务.由于这个任务是我们最后添加进去的依照队列FIFO的原则最后添加的任务一定是最后执行,所以我们在这里能获取到最终的打印结果.但是我们的队列是并发的它执行完任务的顺序是无序的,这么做就一定能获取到最终结果吗?这里由于任务执行复杂度很低所以每个任务执行完成的顺序几乎和添加的顺序是一致的.如果把队列改成串行队列这种做法就严谨了.
2. 在同一个并发队列里,异步执行的任务里再添加一个异步执行的任务
这里是由于异步并发,不会阻塞线程,任务之前不会互相等待,所以会按照15243的顺序执行
3. 线程死锁
在同一个串行队列里异步执行一个同步执行的任务.运行会发生错误,这就是线程死锁.
由于队列是串行的,所以要想执行打印3任务必须要等前一个添加的任务执行完也就是打印完4的任务.但是若想打印4(由于打印3的任务是同步执行的会阻塞线程)就必须等打印3任务执行完成.这就造成了死锁的现象(简单来讲:若想打印4就必须先打印3,若想打印3就必须先打印4);
网友评论