什么是GCD
Grand Central Dispatch (GCD) 是 Apple 开发的一个多核编程的解决方法。该方法在 Mac OS X 10.6 雪豹中首次推出,并随后被引入到了 iOS4.0 中。GCD 是一个替代诸如 NSThread, NSOperationQueue, NSInvocationOperation 等技术的很高效和强大的技术。它为你提供了很多底层工具(比如队列和信号量),你可以组合这些工具来实现自己想要的多线程效果。
GCD API列表
API | 说明 |
---|---|
dispatch_sync() | 同步执行 |
dispatch_async() | 异步执行 |
dispatch_after() | 延时执行 |
dispatch_once() | 一次性执行 |
dispatch_apply() | 提交队列 |
dispatch_queue_create() | 创建队列 |
dispatch_group_create() | 创建队列组 |
dispatch_group_enter() / dispatch_group_leave() | 将队列组中的任务未执行完毕的任务数目加减1(两个函数要配合使用) |
dispatch_group_notify() | 监听队列组执行完毕 |
dispatch_group_wait() | 设置等待时间(返回 0成功,1失败) |
dispatch_semaphore_creat() | 创建信号量 |
dispatch_barrier_sync() | 同步栅栏函数 |
dispatch_barrier_async() | 异步栅栏函数 |
GCD中的队列
Dispatch Queue
Dispatch Queue
是用来执行任务的队列,是GCD
中最基本的元素之一。图示:

一张图片可以很直观地描述GCD与线程之间的关系:

Dispatch Queue种类 | 说明 |
---|---|
Serial Dispatch Queue(串行队列) | 等待现在执行中处理结束 |
Concurrent Dispatch Queue(并发队列) | 不等待现在执行中处理 |
- Serial Dispatch Queue(串行队列): 假设把
任务1
任务2
任务3
任务4
四个任务依次加入到一个Serial Dispatch Queue
中,这个Serial Dispatch Queue
会创建一个线程,依次执行这四个任务。 - Concurrent Dispatch Queue(并发队列): 假设把
任务1
任务2
任务3
任务4
四个任务依次加入到一个Concurrent Dispatch Queue
中,这个Concurrent Dispatch Queue
会创建多个线程,并发执行这四个任务。 - 图示:
Main Dispatch Queue(主队列)
是在主线程执行的dispatch queue
, Main Dispatch Queue(主队列)
是一个Serail Dispatch Queue(串行队列)
。追加到Main Dispatch Queue(主队列)
的处理在主线程的RunLoop
中执行。一般将用户界面更新等必需要在主线程中执行的处理追加到Main Dispatch Queue(主队列)
中。
名称 | Dispatch Queue的种类 | 说明 |
---|---|---|
Main Dispatch Queue | Serial Dispatch Queue | 主线程执行 |
获取Main Dispatch Queue方法:
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
Global Dispatch Queue(全局并发队列)
是所有应用程序都能过使用的Concurrent Dispatch Queue(全局并发队列)
。没有必要通过dispatch_queue_create
函数逐个创建Concurrent Dispatch Queue(并发队列)
,只要获取Global Dispatch Queue(全局并发队列)
使用即可。Global Dispatch Queue(全局并发队列)
有四个优先级
名称 | Dispatch Queue的种类 | 说明 |
---|---|---|
Global Dispatch Queue(High Priority) | Concurrent Dispatch queue | 执行优先级:高(最高) |
Global Dispatch Queue(Default Priority) | Concurrent Dispatch queue | 执行优先级:默认 |
Global Dispatch Queue(Low Priority) | Concurrent Dispatch queue | 执行优先级:低 |
Global Dispatch Queue(Background Priority) | Concurrent Dispatch queue | 执行优先级:后台 |
获取Global Dispatch Queue方法:
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
Main Dispatch Queue
和Global Dispatch Queue
的搭配使用
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/**
* 可并行处理的任务TODO
*/
dispatch_async(dispatch_get_main_queue(), ^{
/**
* 主线程执行
*/
});
});
GCD中队列与线程的搭配使用情况

- 同步函数_串行队列
(不会开启新线程,串行执行任务)
- 同步函数_并发队列
(不会开启新线程,并发执行任务失效!)
- 异步函数_串行队列
(开启新线程,串行执行任务)
- 异步函数_并发队列
(开启新线程,并发执行任务)
GCD实例代码
- 最基础的写法
//1:创建串行队列
dispatch_queue_t queue = dispatch_queue_create("Noah", DISPATCH_QUEUE_SERIAL);
//2:创建任务
dispatch_block_t taskBlock = ^{
NSLog(@"%@",[NSThread currentThread]);
};
//3:利用函数把任务放入队列
dispatch_sync(queue, taskBlock);
- 主队列同步函数
/**
主队列同步
不会开线程
*/
- (void)mainSyncTest{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i<20; i++) {
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
});
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:26:23.840677+0800 001---函数与队列[1750:96869] hello queue
2020-01-27 17:26:23.847367+0800 001---函数与队列[1750:96869] 0-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.847781+0800 001---函数与队列[1750:96869] 1-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848094+0800 001---函数与队列[1750:96869] 2-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848183+0800 001---函数与队列[1750:96869] 3-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848259+0800 001---函数与队列[1750:96869] 4-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848649+0800 001---函数与队列[1750:96869] 5-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848740+0800 001---函数与队列[1750:96869] 6-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.848926+0800 001---函数与队列[1750:96869] 7-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.849003+0800 001---函数与队列[1750:96869] 8-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.849208+0800 001---函数与队列[1750:96869] 9-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852510+0800 001---函数与队列[1750:96869] 10-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852617+0800 001---函数与队列[1750:96869] 11-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852688+0800 001---函数与队列[1750:96869] 12-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852774+0800 001---函数与队列[1750:96869] 13-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852859+0800 001---函数与队列[1750:96869] 14-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.852947+0800 001---函数与队列[1750:96869] 15-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.853023+0800 001---函数与队列[1750:96869] 16-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.853092+0800 001---函数与队列[1750:96869] 17-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.853186+0800 001---函数与队列[1750:96869] 18-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
2020-01-27 17:26:23.853265+0800 001---函数与队列[1750:96869] 19-<NSThread: 0x6000027dd3c0>{number = 1, name = main}
- 主队列异步函数
/**
主队列异步
不会开线程 顺序
*/
- (void)mainAsyncTest{
for (int i = 0; i<20; i++) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:30:43.639916+0800 001---函数与队列[1775:98841] hello queue
2020-01-27 17:30:43.646298+0800 001---函数与队列[1775:98841] 0-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646410+0800 001---函数与队列[1775:98841] 1-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646486+0800 001---函数与队列[1775:98841] 2-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646554+0800 001---函数与队列[1775:98841] 3-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646638+0800 001---函数与队列[1775:98841] 4-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646706+0800 001---函数与队列[1775:98841] 5-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646768+0800 001---函数与队列[1775:98841] 6-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646842+0800 001---函数与队列[1775:98841] 7-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646907+0800 001---函数与队列[1775:98841] 8-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.646982+0800 001---函数与队列[1775:98841] 9-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647046+0800 001---函数与队列[1775:98841] 10-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647144+0800 001---函数与队列[1775:98841] 11-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647326+0800 001---函数与队列[1775:98841] 12-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647526+0800 001---函数与队列[1775:98841] 13-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647701+0800 001---函数与队列[1775:98841] 14-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.647876+0800 001---函数与队列[1775:98841] 15-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.648045+0800 001---函数与队列[1775:98841] 16-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.648204+0800 001---函数与队列[1775:98841] 17-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.648363+0800 001---函数与队列[1775:98841] 18-<NSThread: 0x600003aea900>{number = 1, name = main}
2020-01-27 17:30:43.648511+0800 001---函数与队列[1775:98841] 19-<NSThread: 0x600003aea900>{number = 1, name = main}
- 全局队列异步函数
/**
全局异步
全局队列:一个并发队列
*/
- (void)globalAsyncTest{
for (int i = 0; i<20; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:32:46.849803+0800 001---函数与队列[1796:100014] hello queue
2020-01-27 17:32:46.849839+0800 001---函数与队列[1796:100060] 0-<NSThread: 0x60000004db40>{number = 3, name = (null)}
2020-01-27 17:32:46.849841+0800 001---函数与队列[1796:100073] 1-<NSThread: 0x600000017400>{number = 4, name = (null)}
2020-01-27 17:32:46.849872+0800 001---函数与队列[1796:100061] 2-<NSThread: 0x60000004db00>{number = 5, name = (null)}
2020-01-27 17:32:46.849880+0800 001---函数与队列[1796:100059] 3-<NSThread: 0x60000005fb00>{number = 6, name = (null)}
2020-01-27 17:32:46.849917+0800 001---函数与队列[1796:100073] 6-<NSThread: 0x600000017400>{number = 4, name = (null)}
2020-01-27 17:32:46.849924+0800 001---函数与队列[1796:100060] 7-<NSThread: 0x60000004db40>{number = 3, name = (null)}
2020-01-27 17:32:46.849928+0800 001---函数与队列[1796:100058] 4-<NSThread: 0x600000074700>{number = 7, name = (null)}
2020-01-27 17:32:46.849950+0800 001---函数与队列[1796:100061] 9-<NSThread: 0x60000004db00>{number = 5, name = (null)}
2020-01-27 17:32:46.849964+0800 001---函数与队列[1796:100074] 5-<NSThread: 0x60000007c600>{number = 8, name = (null)}
2020-01-27 17:32:46.849974+0800 001---函数与队列[1796:100059] 10-<NSThread: 0x60000005fb00>{number = 6, name = (null)}
2020-01-27 17:32:46.850015+0800 001---函数与队列[1796:100075] 8-<NSThread: 0x600000064040>{number = 9, name = (null)}
2020-01-27 17:32:46.850033+0800 001---函数与队列[1796:100076] 11-<NSThread: 0x600000078280>{number = 10, name = (null)}
2020-01-27 17:32:46.850021+0800 001---函数与队列[1796:100073] 12-<NSThread: 0x600000017400>{number = 4, name = (null)}
2020-01-27 17:32:46.850065+0800 001---函数与队列[1796:100077] 13-<NSThread: 0x600000070340>{number = 11, name = (null)}
2020-01-27 17:32:46.850068+0800 001---函数与队列[1796:100078] 15-<NSThread: 0x60000004dec0>{number = 12, name = (null)}
2020-01-27 17:32:46.850096+0800 001---函数与队列[1796:100061] 17-<NSThread: 0x60000004db00>{number = 5, name = (null)}
2020-01-27 17:32:46.850107+0800 001---函数与队列[1796:100079] 16-<NSThread: 0x60000005fe00>{number = 13, name = (null)}
2020-01-27 17:32:46.850021+0800 001---函数与队列[1796:100060] 14-<NSThread: 0x60000004db40>{number = 3, name = (null)}
2020-01-27 17:32:46.850138+0800 001---函数与队列[1796:100080] 18-<NSThread: 0x600000078340>{number = 14, name = (null)}
2020-01-27 17:32:46.850161+0800 001---函数与队列[1796:100081] 19-<NSThread: 0x6000000640c0>{number = 15, name = (null)}
- 全局队列同步函数
/**
全局同步
全局队列:一个并发队列
*/
- (void)globalSyncTest{
for (int i = 0; i<20; i++) {
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:34:19.755161+0800 001---函数与队列[1825:101279] 0-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755253+0800 001---函数与队列[1825:101279] 1-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755328+0800 001---函数与队列[1825:101279] 2-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755422+0800 001---函数与队列[1825:101279] 3-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755485+0800 001---函数与队列[1825:101279] 4-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755555+0800 001---函数与队列[1825:101279] 5-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755619+0800 001---函数与队列[1825:101279] 6-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755695+0800 001---函数与队列[1825:101279] 7-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755760+0800 001---函数与队列[1825:101279] 8-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755825+0800 001---函数与队列[1825:101279] 9-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755887+0800 001---函数与队列[1825:101279] 10-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.755949+0800 001---函数与队列[1825:101279] 11-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763221+0800 001---函数与队列[1825:101279] 12-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763318+0800 001---函数与队列[1825:101279] 13-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763412+0800 001---函数与队列[1825:101279] 14-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763468+0800 001---函数与队列[1825:101279] 15-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763553+0800 001---函数与队列[1825:101279] 16-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763615+0800 001---函数与队列[1825:101279] 17-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763681+0800 001---函数与队列[1825:101279] 18-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763744+0800 001---函数与队列[1825:101279] 19-<NSThread: 0x600003aa93c0>{number = 1, name = main}
2020-01-27 17:34:19.763795+0800 001---函数与队列[1825:101279] hello queue
- 同步队列并发函数
/**
同步并发
不开线程:就算并发出来,没有坑位接受,所以顺序执行
*/
- (void)concurrentSyncTest{
//1:创建并发队列
dispatch_queue_t queue = dispatch_queue_create("Noah", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i<20; i++) {
dispatch_sync(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:36:47.811986+0800 001---函数与队列[1846:102561] 0-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812081+0800 001---函数与队列[1846:102561] 1-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812152+0800 001---函数与队列[1846:102561] 2-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812213+0800 001---函数与队列[1846:102561] 3-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812280+0800 001---函数与队列[1846:102561] 4-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812340+0800 001---函数与队列[1846:102561] 5-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812396+0800 001---函数与队列[1846:102561] 6-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812456+0800 001---函数与队列[1846:102561] 7-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812526+0800 001---函数与队列[1846:102561] 8-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812588+0800 001---函数与队列[1846:102561] 9-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812649+0800 001---函数与队列[1846:102561] 10-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.812728+0800 001---函数与队列[1846:102561] 11-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820467+0800 001---函数与队列[1846:102561] 12-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820589+0800 001---函数与队列[1846:102561] 13-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820703+0800 001---函数与队列[1846:102561] 14-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820774+0800 001---函数与队列[1846:102561] 15-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820867+0800 001---函数与队列[1846:102561] 16-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.820949+0800 001---函数与队列[1846:102561] 17-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.821044+0800 001---函数与队列[1846:102561] 18-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.821108+0800 001---函数与队列[1846:102561] 19-<NSThread: 0x600000cd93c0>{number = 1, name = main}
2020-01-27 17:36:47.821180+0800 001---函数与队列[1846:102561] hello queue
- 异步队列并发函数
/**
异步并发
一次多个 没有顺序
开线程
*/
- (void)concurrentAsyncTest{
//1:创建并发队列
dispatch_queue_t queue = dispatch_queue_create("Noah", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i<20; i++) {
dispatch_async(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:44:03.551880+0800 001---函数与队列[1878:104767] hello queue
2020-01-27 17:44:03.551943+0800 001---函数与队列[1878:104812] 0-<NSThread: 0x6000005797c0>{number = 3, name = (null)}
2020-01-27 17:44:03.551945+0800 001---函数与队列[1878:104814] 3-<NSThread: 0x6000005695c0>{number = 6, name = (null)}
2020-01-27 17:44:03.551950+0800 001---函数与队列[1878:104813] 1-<NSThread: 0x60000050afc0>{number = 4, name = (null)}
2020-01-27 17:44:03.551951+0800 001---函数与队列[1878:104825] 4-<NSThread: 0x600000543a00>{number = 7, name = (null)}
2020-01-27 17:44:03.551951+0800 001---函数与队列[1878:104815] 2-<NSThread: 0x600000543a80>{number = 5, name = (null)}
2020-01-27 17:44:03.551984+0800 001---函数与队列[1878:104826] 5-<NSThread: 0x60000050af40>{number = 8, name = (null)}
2020-01-27 17:44:03.552022+0800 001---函数与队列[1878:104812] 8-<NSThread: 0x6000005797c0>{number = 3, name = (null)}
2020-01-27 17:44:03.552033+0800 001---函数与队列[1878:104814] 9-<NSThread: 0x6000005695c0>{number = 6, name = (null)}
2020-01-27 17:44:03.552038+0800 001---\345\2072020-01-27 17:44:03.552075+0800 001---函数与队列[1878:104829] 10-<NSThread: 0x60000050af80>{number = 11, name = (null)}
2020-01-27 17:44:03.552083+0800 001---函数与队列[1878:104828] 7-<NSThread: 0x600000564340>{number = 10, name = (null)}
2020-01-27 17:44:03.552093+0800 001---函数与队列[1878:104826] 15-<NSThread: 0x60000050af40>{number = 8, name = (null)}
2020-01-27 17:44:03.552093+0800 001---函数与队列[1878:104815] 13-<NSThread: 0x600000543a80>{number = 5, name = (null)}
2020-01-27 17:44:03.552198+0800 001---函数与队列[1878:104834] 19-<NSThread: 0x600000575540>{number = 16, name = (null)}
2020-01-27 17:44:03.552113+0800 001---函数与队列[1878:104830] 14-<NSThread: 0x60000054c6c0>{number = 12, name = (null)}
2020-01-27 17:44:03.552135+0800 001---函数与队列[1878:104831] 16-<NSThread: 0x6000005643c0>{number = 13, name = (null)}
2020-01-27 17:44:03.552150+0800 001---函数与队列[1878:104832] 17-<NSThread: 0x600000569a00>{number = 14, name = (null)}
2020-01-27 17:44:03.552179+0800 001---函数与队列[1878:104833] 18-<NSThread: 0x600000543d80>{number = 15, name = (null)}
\275数与队列[1878:104827] 6-<NSThread: 0x60000054c640>{number = 9, name = (null)}
2020-01-27 17:44:03.552061+0800 001---函数与队列[1878:104813] 11-<NSThread: 0x60000050afc0>{number = 4, name = (null)}
2020-01-27 17:44:03.552063+0800 001---函数与队列[1878:104825] 12-<NSThread: 0x600000543a00>{number = 7, name = (null)}
- 串行队列异步函数
/**
串行异步队列
1:异步执行:会开启线程,顺序跟着耗时走
*/
- (void)serialAsyncTest{
//1:创建串行队列
dispatch_queue_t queue = dispatch_queue_create("Noah", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i<20; i++) {
dispatch_async(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:47:12.046872+0800 001---函数与队列[1896:106036] hello queue
2020-01-27 17:47:12.046903+0800 001---函数与队列[1896:106075] 0-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.046981+0800 001---函数与队列[1896:106075] 1-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047066+0800 001---函数与队列[1896:106075] 2-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047141+0800 001---函数与队列[1896:106075] 3-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047218+0800 001---函数与队列[1896:106075] 4-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047319+0800 001---函数与队列[1896:106075] 5-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047390+0800 001---函数与队列[1896:106075] 6-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047531+0800 001---函数与队列[1896:106075] 7-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047612+0800 001---函数与队列[1896:106075] 8-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047705+0800 001---函数与队列[1896:106075] 9-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047799+0800 001---函数与队列[1896:106075] 10-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.047876+0800 001---函数与队列[1896:106075] 11-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.056948+0800 001---函数与队列[1896:106075] 12-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057028+0800 001---函数与队列[1896:106075] 13-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057104+0800 001---函数与队列[1896:106075] 14-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057165+0800 001---函数与队列[1896:106075] 15-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057237+0800 001---函数与队列[1896:106075] 16-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057312+0800 001---函数与队列[1896:106075] 17-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057394+0800 001---函数与队列[1896:106075] 18-<NSThread: 0x600003450900>{number = 3, name = (null)}
2020-01-27 17:47:12.057469+0800 001---函数与队列[1896:106075] 19-<NSThread: 0x600003450900>{number = 3, name = (null)}
- 串行队列同步函数
/**
串行同步队列
1:同步执行:一行一行代码从上向下执行,当前代码不执行完成,不会执行后续代码 同步不会开启线程
2:串行队列:一个一个的调度任务,前一个任务没有执行完成,不会调度后面的任务
*/
- (void)serialSyncTest{
//1:创建串行队列
dispatch_queue_t queue = dispatch_queue_create("Noah", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i<20; i++) {
dispatch_sync(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
// 打印
2020-01-27 17:48:54.224033+0800 001---函数与队列[1920:107306] 0-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224142+0800 001---函数与队列[1920:107306] 1-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224214+0800 001---函数与队列[1920:107306] 2-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224270+0800 001---函数与队列[1920:107306] 3-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224340+0800 001---函数与队列[1920:107306] 4-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224398+0800 001---函数与队列[1920:107306] 5-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224460+0800 001---函数与队列[1920:107306] 6-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224515+0800 001---函数与队列[1920:107306] 7-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224583+0800 001---函数与队列[1920:107306] 8-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224644+0800 001---函数与队列[1920:107306] 9-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224712+0800 001---函数与队列[1920:107306] 10-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224774+0800 001---函数与队列[1920:107306] 11-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.224833+0800 001---函数与队列[1920:107306] 12-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232531+0800 001---函数与队列[1920:107306] 13-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232614+0800 001---函数与队列[1920:107306] 14-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232682+0800 001---函数与队列[1920:107306] 15-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232741+0800 001---函数与队列[1920:107306] 16-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232820+0800 001---函数与队列[1920:107306] 17-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232890+0800 001---函数与队列[1920:107306] 18-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.232948+0800 001---函数与队列[1920:107306] 19-<NSThread: 0x6000012ae940>{number = 1, name = main}
2020-01-27 17:48:54.233001+0800 001---函数与队列[1920:107306] hello queue
dispatch_after
使用
/**
延迟测试
*/
- (void)delayDemo{
//NSEC_PER_SEC : 1000000000ull 纳秒每秒 0.0000001 可以这么做参数
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC));
//串行队列来测试 延迟的方法是不是异步的!
dispatch_queue_t queue = dispatch_queue_create("com.lg.cn", DISPATCH_QUEUE_SERIAL);
dispatch_after(time, queue, ^{
NSLog(@"延迟打印");
});
NSLog(@"打印完了?");
}
//打印
2020-01-27 19:38:24.727940+0800 005---GCD进阶使用(下)[2216:130497] 打印完了?
2020-01-27 19:38:25.816560+0800 005---GCD进阶使用(下)[2216:130584] 延迟打印
dispatch_once
使用
/**
单例
*/
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
dispatch_group_async
使用
/**
调度组测试
*/
- (void)groupDemo{
//创建调度组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_queue_t queue1 = dispatch_queue_create("com.nh.cn", DISPATCH_QUEUE_CONCURRENT);
// SIGNAL
dispatch_group_async(group, queue, ^{
NSString *logoStr = @"https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png";
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:logoStr]];
UIImage *image = [UIImage imageWithData:data];
[self.mArray addObject:image];
});
dispatch_group_async(group, queue1, ^{
// afn --- sdk : queue: com.afn.cn
NSString *logoStr = @"https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png";
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:logoStr]];
UIImage *image = [UIImage imageWithData:data];
[self.mArray addObject:image];
});
__block UIImage *newImage = nil;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"数组个数:%ld",self.mArray.count);
});
}
// 打印
2020-01-27 20:24:30.544956+0800 005---GCD进阶使用(下)[2546:203237] 数组个数:2
- 调度组内部方法使用
/**
调度组内部方法 enter - leave
*/
- (void)groupDemo2{
// 问题: 如果 dispatch_group_enter 多 dispatch_group_leave 不会调用通知
// dispatch_group_enter 少 dispatch_group_leave 奔溃
// 成对存在
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
// dispatch_group_async -- 下节课的源码分析 --封装意思
dispatch_async(queue, ^{
NSLog(@"第一个走完了");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"第二个走完了");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"所有任务完成,可以更新UI");
});
}
// 打印
2020-01-27 20:24:49.213355+0800 005---GCD进阶使用(下)[2555:203694] 第一个走完了
2020-01-27 20:24:49.213363+0800 005---GCD进阶使用(下)[2555:203697] 第二个走完了
- 栅栏函数
在使用栅栏函数时.使用自定义队列才有意义,如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个同步函数的作用
// dispatch_barrier_sync
- (void)demo2{
// 你全部下载完毕之后,我才能处理
dispatch_queue_t concurrentQueue = dispatch_queue_create("noah", DISPATCH_QUEUE_CONCURRENT);
// 全局 -- 堵塞
// 系统GG -- 设计
// 这里要注意,如果用的是全局队列,使用栅栏函数是无效的
// dispatch_queue_t concurrentQueue = dispatch_get_global_queue(0, 0);
/* 1.异步函数 */
dispatch_async(concurrentQueue, ^{
// 请求token -- 线程安全
for (NSUInteger i = 0; i < 5; i++) {
NSLog(@"download1-%zd-%@",i,[NSThread currentThread]);
}
});
//
dispatch_async(concurrentQueue, ^{
for (NSUInteger i = 0; i < 5; i++) {
NSLog(@"download2-%zd-%@",i,[NSThread currentThread]);
}
});
/* 2. 栅栏函数 */
dispatch_barrier_sync(concurrentQueue, ^{
NSLog(@"---------------------%@------------------------",[NSThread currentThread]);
});
NSLog(@"加载那么多,喘口气!!!");
/* 3. 异步函数 */
dispatch_async(concurrentQueue, ^{
for (NSUInteger i = 0; i < 5; i++) {
NSLog(@"日常处理3-%zd-%@",i,[NSThread currentThread]);
}
});
NSLog(@"************起来干!!");
dispatch_async(concurrentQueue, ^{
for (NSUInteger i = 0; i < 5; i++) {
NSLog(@"日常处理4-%zd-%@",i,[NSThread currentThread]);
}
});
}
// 打印
2020-01-27 20:56:33.782415+0800 004--GCD进阶使用[2824:318070] download1-0-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.782420+0800 004--GCD进阶使用[2824:318073] download2-0-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.782515+0800 004--GCD进阶使用[2824:318070] download1-1-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.782521+0800 004--GCD进阶使用[2824:318073] download2-1-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.782599+0800 004--GCD进阶使用[2824:318070] download1-2-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.782609+0800 004--GCD进阶使用[2824:318073] download2-2-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.782659+0800 004--GCD进阶使用[2824:318070] download1-3-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.782694+0800 004--GCD进阶使用[2824:318073] download2-3-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.782755+0800 004--GCD进阶使用[2824:318070] download1-4-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.782759+0800 004--GCD进阶使用[2824:318073] download2-4-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.782938+0800 004--GCD进阶使用[2824:318033] ---------------------<NSThread: 0x600003902940>{number = 1, name = main}------------------------
2020-01-27 20:56:33.783020+0800 004--GCD进阶使用[2824:318033] 加载那么多,喘口气!!!
2020-01-27 20:56:33.783106+0800 004--GCD进阶使用[2824:318033] ************起来干!!
2020-01-27 20:56:33.783135+0800 004--GCD进阶使用[2824:318070] 日常处理3-0-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.783204+0800 004--GCD进阶使用[2824:318073] 日常处理4-0-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.783258+0800 004--GCD进阶使用[2824:318070] 日常处理3-1-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.783343+0800 004--GCD进阶使用[2824:318073] 日常处理4-1-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.792221+0800 004--GCD进阶使用[2824:318070] 日常处理3-2-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.792238+0800 004--GCD进阶使用[2824:318073] 日常处理4-2-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.792311+0800 004--GCD进阶使用[2824:318070] 日常处理3-3-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.792325+0800 004--GCD进阶使用[2824:318073] 日常处理4-3-<NSThread: 0x600003974240>{number = 4, name = (null)}
2020-01-27 20:56:33.792383+0800 004--GCD进阶使用[2824:318070] 日常处理3-4-<NSThread: 0x60000398a480>{number = 3, name = (null)}
2020-01-27 20:56:33.792399+0800 004--GCD进阶使用[2824:318073] 日常处理4-4-<NSThread: 0x600003974240>{number = 4, name = (null)}
// dispatch_barrier_async函数
/**
可变数组 线程不安全 解决办法
*/
- (void)demo3{
// 顺序执行
// 线程安全
dispatch_queue_t concurrentQueue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
// signal -- 线程BUG
for (int i = 0; i<2000; i++) {
dispatch_async(concurrentQueue, ^{
NSString *imageName = [NSString stringWithFormat:@"%d.jpg", (i % 10)];
NSURL *url = [[NSBundle mainBundle] URLForResource:imageName withExtension:nil];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 这代码如果不加处理会导致崩溃,因为多条线程同时操作一块内存会导致崩溃,可以加锁,也可以使用异步栅栏函数去处理
//[self.mArray addObject:image];
dispatch_barrier_async(concurrentQueue, ^{
[self.mArray addObject:image];
});
});
}
}
其实dispatch_barrier_async与dispatch_barrier_sync两者之间并没有很大的区别,如果用dispatch_barrier_async的话就不会堵塞,用dispatch_barrier_sync就会堵塞,主要看功能代码逻辑去选择用哪个函数,两者的功能是一样的