GCD系列
- GCD基础
- GCD进阶函数
- 调度组dispatch_group
- 信号量dispatch_semaphore
学习GCD之前,我们需要了解比较重要的几个概念
同步 & 异步
同步:同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。
异步:异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。
并发 & 串行
串行:每次只有一个任务被执行。让任务一个接着一个地执行。
并发:多个任务并发(同时)执行。
串行是一次只能执行一个任务,并行是一次能执行多个任务。并行是CPU的多核芯同时执行多个任务 并发是单核CPU交替执行两个任务。
队列&任务
同步、异步是用来表示线程,并发、串行是用来形容队列的
GCD中的三种队列类型
- 主队列串行队列(Main Dispatch Queue)
使用dispatch_get_main_queue()
获得主队列。 - 全局并发队列(Global Dispatch Queue)。
使用dispatch_get_global_queue(long identifier, unsigned long flags)
来获取。第一个参数表示优先级,使用DISPATCH_QUEUE_PRIORITY_DEFAULT就行,第二个参数暂时没用,传0
// 主队列的获取方法
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//全局队列的获取方法,第一个参数表示优先级,使用DISPATCH_QUEUE_PRIORITY_DEFAULT就行,第二个参数暂时没用,传0
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
- 自定义串行/并行队列
使用dispatch_queue_create( )
创建
/*
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
参数说明:
* @param label:队列的唯一标识符,用于 DEBUG,可为空,Dispatch Queue 的名称推荐使用应用程序 ID 这种逆序全程域名
* @param attr:用来标识是串行队列(DISPATCH_QUEUE_SERIAL)还是并发队列(DISPATCH_QUEUE_CONCURRENT)。
* 关于attr文档后面还有一句说明:or the result of a call to a dispatch_queue_attr_make_with_* function,一般不用
*/
//创建串行队列
dispatch_queue_t queue1 = dispatch_queue_create("elaine.yin", DISPATCH_QUEUE_SERIAL);
//创建并发队列
dispatch_queue_t queue2 = dispatch_queue_create("elaine.yin", DISPATCH_QUEUE_CONCURRENT);
GCD队列与执行方式的组合
先来张图镇楼
1. 同步+并发
结论:不会开启新线程,任务顺序执行
show the code
#pragma mark - 同步执行 + 并发队列
//同步执行 + 并发队列
- (void)SyncConcurrentTest {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"SyncConcurrent---begin");
dispatch_queue_t queue = dispatch_queue_create("SyncConcurrent.elaine.yin", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"1:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
});
NSLog(@"SyncConcurrent---end");
}
2.异步 + 并发
结论:开启多个线程,异步执行
show the code
#pragma mark - 异步执行 + 并发队列
- (void)AsyncConcurrentTest {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"AsyncConcurrent---begin");
dispatch_queue_t queue = dispatch_queue_create("AsyncConcurrent.elaine.yin", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"3:%@",[NSThread currentThread]);
});
NSLog(@"AsyncConcurrent---end");
}
3. 同步 + 串行
不开启新线程,任务按照顺序执行
show the code
- (void)SyncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"SyncSerial---begin");
dispatch_queue_t queue = dispatch_queue_create("SyncSerial.elaine.yin", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"1:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"2:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"3:%@",[NSThread currentThread]);
});
NSLog(@"SyncSerial---end");
}
4. 异步 + 串行
结论:开启一个新线程,任务按照顺序执行
show the code
- (void)AsyncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"AsyncSerial---begin");
dispatch_queue_t queue = dispatch_queue_create("AsyncSerial.elaine.yin", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
}
});
NSLog(@"AsyncSerial---end");
}
5. 异步 + 主队列
结论:不开启新线程,任务按照顺序执行
show the code
- (void)AsyncMainQueue {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"AsyncMainQueue---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
}
});
NSLog(@"AsyncMainQueue---end");
}
6. 同步 + 主队列
结论:死锁
show the code
- (void)SyncMainQueue {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"SyncMainQueue---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (NSInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
}
});
NSLog(@"SyncMainQueue---end");
}
dispatch_suspend(queue) //暂停某个队列 dispatch_suspend挂起指定的dispatch_queue
dispatch_resume(queue) //恢复某个队列 dispatch_resume恢复指定的dispatch_queue
参考链接:
https://www.jianshu.com/p/2d57c72016c6
http://www.cocoachina.com/ios/20161031/17887.html