GCD概要
3.3.1 什么是GCD

PS : GCD 使用了简介的记述方式实现了复杂繁琐的多线程编程。
到引入GCD之前, cocoa只给你在NSObject类中实现了有关的多线程变成技术。 perform... 有关的方法。
FOUNDATION_EXPORT NSNotificationName const NSWillBecomeMultiThreadedNotification;
FOUNDATION_EXPORT NSNotificationName const NSDidBecomeSingleThreadedNotification;
FOUNDATION_EXPORT NSNotificationName const NSThreadWillExitNotification; // 可以用来监听线程是否已经销毁了?
// 测试, 发现我们在iOS上的环境,只有最后一个通知会收到,大概是因为app启动的时候就已经是多线程了。
线程的通知。
@interface NSObject (NSThreadPerformAdditions)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
// equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 主线程、 后台线程
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 线程的后向方式,执行在哪个生成的子线程里面。
// equivalent to the first method with kCFRunLoopCommonModes
@end
PS: perforSelector 系方法确实要比使用NSThread 类精心多线程编程简单。 当时相比GCD,GCD更加的简介。
没有多线程的程序执行示意图
多线程执行示意图
多线程的问题
iOS为什么需要多线程?
可保证应用程序的响应性能。
因为主线程是渲染UI ,触摸屏幕时间等。 不能够妨碍主线程的循环执行刷新等等。
![]()
3.2 GCD 的API
3.2.1 dispatch queue (队列)
定义:开发者要做的只是定义想要执行的任务并追加到适当的 dispatch queue 中。
// 基本执行的结构
dispatch_async(queue, ^{
// 想执行的任务
});
dispatch queue :执行处理的等待队列。
block:block 语法中记述想之心的处理并将其追加大搜dispatch queue 中。
追加顺序: FIFO
dispatch queue 分类:
serial dispatch queue 串行 (等待上一个任务完成)
concurrent dispatch queue 并行 (不用等待上一个任务完成)
两种队列的差异
两种队列示意图
并行队列,可以让多个任务同时执行。 但并行执行的处理数量取决于当前系统的状态。 iOS基于dispatch queue 中的处理数、cpu核数以及cpu负荷等当前系统的状态决定concurrent dispatch queue 中并行执行的处理数。
所谓“并行执行”, 就是使用多个线程同事执行多个处理。
![]()
(1)iOS核心 —— XNU 内核决定应当使用的线程数,并只能生成所需的线程执行处理。
(2)当处理结束, 应当执行的处理数减少时, XNU内核会结束不再需要的线程。
(3)XNU内核仅使用concurrent dispatch queue 便可完美地管理并执行多个处理的线程。
在不想改变执行的处理顺序或不想并行之心多个处理时
—— serial dispatch queue
dispatch_queue_create
decodeQue = dispatch_queue_create("KMLoadingImageViewDecodeQueue", DISPATCH_QUEUE_SERIAL);
创建了一个并行的队列
![]()
![]()
串行队列可以让线程安全
![]()
生成队列并使用
好像现在并不需要程序员进行释放这个内容
Main dispatch queue 、global dispatch queue
Main dispatch queue : 主线程队列 (serial)
![]()
global dispatch queue : 全局线程 (concurrent dispatch queue)
![]()

3.2.4 dispatch_set_target_queue




dispatch_queue_t serialQueue1 = dispatch_queue_create("com.gcd.setTargetQueue2.serialQueue1", NULL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("com.gcd.setTargetQueue2.serialQueue2", NULL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("com.gcd.setTargetQueue2.serialQueue3", NULL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("com.gcd.setTargetQueue2.serialQueue4", NULL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("com.gcd.setTargetQueue2.serialQueue5", NULL);
//创建目标串行队列 ,也就是将哪些队列放到这个队列里面执行
dispatch_queue_t targetSerialQueue = dispatch_queue_create("com.gcd.setTargetQueue2.targetSerialQueue", NULL);
//设置执行阶层
dispatch_set_target_queue(serialQueue1, targetSerialQueue);
dispatch_set_target_queue(serialQueue3, targetSerialQueue);
dispatch_set_target_queue(serialQueue2, targetSerialQueue);
dispatch_set_target_queue(serialQueue4, targetSerialQueue);
dispatch_set_target_queue(serialQueue5, targetSerialQueue);
dispatch_async(serialQueue1, ^{
NSLog(@"1");
});
dispatch_async(serialQueue2, ^{
NSLog(@"2");
});
dispatch_async(serialQueue3, ^{
NSLog(@"3");
});
dispatch_async(serialQueue4, ^{
NSLog(@"4");
});
dispatch_async(serialQueue5, ^{
NSLog(@"5");
});
// 即为将那5个队列,合并到同一个队列里面
3.2.5 dispatch_after 追加时间处理
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
block();
});
PS:0.3秒后执行内容
3.2.6 dispatch group [常用]

可以和group有关的方法进行使用。

3.2.7 dispatch_barrier_async 栅栏
实现了一个变量的读取的线程安全。 和读写锁有类似的功能。




这个方法还会实现,有关的一个变量安全读写的的线程安全问题。就是和上面的共享数据的读写问题。
3.2.8 dispatch_sync 同步的方法,没有开启线程能力。

注意造成死锁。
如果一个并发队列中,有async使用,也有意对应的async使用。 那么这个将会如何处理?
// 并发队列不要求上一个任务完成再执行, 而sync是要求上一个任务完成之后再执行。

3.2.9 dispatch_apply

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"lt - index:%zd",index);
});
NSLog(@"done ");



对于批量处理相同的任务dispatch_apply 相较于 for 和 while 能更合理的使用资源
当时iOS中,里面就有了一个并发的遍历方式了;


3.2.11 dispatch semaphore 信号量处理 【常用】
可以说是比serial queue 以及dispatch_barrier_aync 方法更加细粒度进行控制的。
3.2.12 dispatch_once 【常用】
保证在应用程序执行中只执行一次指定处理的API。
3.2.13 dispatch I/O


GCD 有效读取数千个小文件
3.3 GCD 的实现 —— 这个底层内容实现,先不管。
3.3.1 dispatch queue





3.3.2 dispatch source









有关具体的方法, 可以去看一下libdispatch 这个库的内容。
网友评论