一、概念回顾
1、GCD全称 Grand Central Dispatch ,是纯C语言,提供了非常多强大的函数,来进行系统线程的管理。
2、优势:GCD是苹果公司为多核的并行运算提出的解决方案。GCD会自动利用更多的CPU内核,会自动管理线程的生命周期(创建线程、调度任务、销毁线程),程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码。
3、GCD的两个核心:
(1)队列:GCD会从队列中取出任务,按照不同情况,放到对应的线程中执行,遵循FIFO原则。
队列共分有四种:
a、串行 :任务一个接一个的执行。
b、并发 :可以让任务同时执行,就是开启多个线程执行任务。
c、全局 :本质就是并发队列,区别:没有名称,不可跟踪;在MRC中释放次数不一样。
通过函数 dispatch_get_global_queue(<#long identifier#>, <#unsigned long flags#>)获得,第一个参数是优先级,第二个是预留(无用),一般二者都设为0。
d、主队列 :在主线程中顺序执行,有死锁现象(主队列同步执行的情况)。
(2)任务:就是要处理的事情。
任务处理(操作)方式有两种
a、同步 :在当前线程执行,不开辟新的线程。
b、异步 :在新的线程中执行任务,可以开启新的一条或多条线程。
4、队列和任务执行方式的组合
5、死锁描述:向串行队列里面分派同步任务(dispatch_sync)
二、实验观察线程管理情况
各种情况都写在viewDidLoad中,需要时打开注释,方便比较和查阅
- (void)viewDidLoad { [super viewDidLoad]; //串行队列 dispatch_queue_t serial = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL); //并行队列 dispatch_queue_t concurrent = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT); //创建block1 dispatch_block_t block1 = ^{ //特意将第一个任务延迟一秒,用来观察执行顺序 [NSThread sleepForTimeInterval:1]; NSLog(@" block1 ==> %@",[NSThread currentThread]); }; //创建block2 dispatch_block_t block2 = ^{ NSLog(@" block2 ==> %@",[NSThread currentThread]); }; #pragma mark - 串行同步 :在当前线程,FIFO顺序执行任务 // dispatch_sync(serial, block1); // dispatch_sync(serial, block2); #pragma mark - 串行异步 :新建一个线程,出队列后按FIFO顺序执行 // dispatch_async(serial, block1); // dispatch_async(serial, block2); #pragma mark - 并发同步 :在当前线程,出队列后顺序执行 // dispatch_sync(concurrent, block1); // dispatch_sync(concurrent, block2); #pragma mark - 并发异步 :创建N个新线程,出队列后随机(同时)执行 // dispatch_async(concurrent, block1); // dispatch_async(concurrent, block2); #pragma mark - 全局同步 :类似并发同步,全局队列是通过函数获得的 // dispatch_sync(dispatch_get_global_queue(0, 0), block1); // dispatch_sync(dispatch_get_global_queue(0, 0), block2); #pragma mark - 全局异步 :类似并发异步 // dispatch_async(dispatch_get_global_queue(0, 0), block1); // dispatch_async(dispatch_get_global_queue(0, 0), block2); #pragma mark - 主队列同步(死锁):主线程等待主队列中任务执行完毕(一直挂起,不是空闲)后面的代码都无法运行,然而主队列中的任务又在等待主线程空闲(也一直挂起,等待着主线程可以闲下来),所有两者相互等待,形成死锁。 // dispatch_sync(dispatch_get_main_queue(), block1); // dispatch_sync(dispatch_get_main_queue(), block2); #pragma mark - 主队列同步(解死锁):加上一个全局异步,这样主线程不会卡住,主线程可以执行完它的代码,回过头来(此时空闲了),处理主队列里面的任务,不会锁死。 // dispatch_async(dispatch_get_global_queue(0, 0), ^{ // NSLog(@"我是解锁的开始,此时线程 ===》%@ ",[NSThread currentThread]); // dispatch_sync(dispatch_get_main_queue(), block1); // dispatch_sync(dispatch_get_main_queue(), block2); // NSLog(@"死锁被解开了!!%@ ",[NSThread currentThread]); // }); #pragma mark - 主队列异步 : 主线程空闲时才执行主队列中的内容,出队列顺序执行 // dispatch_async(dispatch_get_main_queue(), block1); // dispatch_async(dispatch_get_main_queue(), block2); NSLog(@" (主线程)我是写在程序最后的 =====》 end"); }
贴上几种组合的执行结果图(不是所有)
1、串行异步
2、并发同步
3、主队列同步 (解开死锁的情况)
4、主队列异步
三、总结
GCD管理线程,功能强大:有没有新线程看是否同步——异步;有没有顺序执行看是否串行——并行。
还有多种线程管理的方式:pthread、NSThread、NSOperation(NSInvocationOperation、NSBlockOperation),各有优缺点,以及使用的场景,以后再做讨论。