定义在object.h中,是dispatch系列数据结构的基础结构,类似于NSObject基类,如dispatch_queue_t、dispatch_group_t、dispatch_source_t等都可以直接调用dispatch_object_t相关的函数,GCD使用宏定义隐藏了其内部实现,其实他们都是遵循同一个协议的NSObject类型的对象,如下图
object.h内部定义了一系列内存语义和操作函数,如下
dispatch_object_t内存语义
void dispatch_retain(dispatch_object_t object); // MRC下retain内存语义
void dispatch_release(dispatch_object_t object); // MRC下release内存语义
MRC下内存管理语句,ARC下禁用
dispatch_object_t绑定上下文
void dispatch_set_context(dispatch_object_t object, void *context); // 给dispatch对象绑定上下文
void *dispatch_get_context(dispatch_object_t object); // 返回dispatch对象绑定的上下文
void dispatch_set_finalizer_f(dispatch_object_t object, dispatch_function_t finalizer); // 绑定函数指针,当dispatch任务执行完毕会通过该函数回调并且带回绑定的上下文
注意:
只有由dispatch_queue_create创建出来的队列设置上下文才有效,主队列
dispatch_get_main_queue
和全局队列dispatch_get_global_queue(0, 0)
苹果禁止修改上下文,因为苹果有自己的实现,因此我们常说这两个是特殊的队列
演示:
void finalizer(void *context) {
id object = (__bridge_transfer id)context;
NSLog(@"执行finalizer:%@", object);
}
dispatch_queue_t dispatchObject = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
void *context = (__bridge_retained void *)self;
dispatch_set_context(dispatchObject, context);
dispatch_set_finalizer_f(dispatchObject, finalizer);
NSInteger count = 10;
while (count--) {
dispatch_async(dispatchObject, ^{
usleep(1000 * 1000); // 线程休眠一秒
NSLog(@"dispatchObject %ld:执行完毕", (long)count);
});
}
输出:
2021-08-19 15:30:14.484310+0800 GCDDemo[3254:1673360] dispatchObject 9:执行完毕
2021-08-19 15:30:14.484553+0800 GCDDemo[3254:1673359] dispatchObject 8:执行完毕
2021-08-19 15:30:14.485017+0800 GCDDemo[3254:1673358] dispatchObject 7:执行完毕
2021-08-19 15:30:14.487532+0800 GCDDemo[3254:1673368] dispatchObject 1:执行完毕
2021-08-19 15:30:14.487604+0800 GCDDemo[3254:1673369] dispatchObject 0:执行完毕
2021-08-19 15:30:14.489625+0800 GCDDemo[3254:1673363] dispatchObject 6:执行完毕
2021-08-19 15:30:14.489760+0800 GCDDemo[3254:1673357] dispatchObject 5:执行完毕
2021-08-19 15:30:14.490028+0800 GCDDemo[3254:1673364] dispatchObject 4:执行完毕
2021-08-19 15:30:14.490185+0800 GCDDemo[3254:1673365] dispatchObject 3:执行完毕
2021-08-19 15:30:14.490442+0800 GCDDemo[3254:1673367] dispatchObject 2:执行完毕
2021-08-19 15:30:14.492204+0800 GCDDemo[3254:1673367] 执行finalizer:<ViewController: 0x153f09550>
使用场景:
如上待到所有并发任务执行完成,就会执行finalizer函数,当然串行队列也是一样,只是会按照顺序执行,当一组任务执行完毕的时候需要执行一个统一的操作,这个时候就可以用绑定上下文来实现
当然苹果给我们提供了更便捷的dispatch_group_t系列api,这个后面文章再讲
dispatch_activate
定义如下,用于激活非激活状态dispatch_object_t
void
dispatch_activate(dispatch_object_t object);
注意:
主队列
dispatch_get_main_queue
和全局队列dispatch_get_global_queue(0, 0)
是激活态的,我们通过dispatch_queue_create创建的队列可以用第二个参数指定激活状态
- DISPATCH_QUEUE_SERIAL 串行队列
- DISPATCH_QUEUE_SERIAL_INACTIVE 非激活态串行队列
- DISPATCH_QUEUE_CONCURRENT 并发队列
- DISPATCH_QUEUE_CONCURRENT_INACTIVE 非激活态并发队列
演示:
self.concurrentQueue = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT_INACTIVE);
NSInteger count = 10;
while (count--) {
dispatch_async(self.concurrentQueue, ^{
usleep(1000 * 1000); // 线程休眠一秒
NSLog(@"dispatchObject %ld:执行完毕", (long)count);
});
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_activate(self.concurrentQueue);
});
输出
2021-08-19 17:23:32.521423+0800 GCDDemo[3317:1706577] dispatchObject 9:执行完毕
2021-08-19 17:23:32.521596+0800 GCDDemo[3317:1706571] dispatchObject 8:执行完毕
2021-08-19 17:23:32.521444+0800 GCDDemo[3317:1706597] dispatchObject 0:执行完毕
2021-08-19 17:23:32.522131+0800 GCDDemo[3317:1706573] dispatchObject 7:执行完毕
2021-08-19 17:23:32.522333+0800 GCDDemo[3317:1706578] dispatchObject 6:执行完毕
2021-08-19 17:23:32.522519+0800 GCDDemo[3317:1706592] dispatchObject 5:执行完毕
2021-08-19 17:23:32.522710+0800 GCDDemo[3317:1706593] dispatchObject 4:执行完毕
2021-08-19 17:23:32.522895+0800 GCDDemo[3317:1706594] dispatchObject 3:执行完毕
2021-08-19 17:23:32.522985+0800 GCDDemo[3317:1706595] dispatchObject 2:执行完毕
2021-08-19 17:23:32.523146+0800 GCDDemo[3317:1706596] dispatchObject 1:执行完毕
使用场景:
可以用于构建备忘录模式,进行操作存档,当然与传统备忘录模式还有些区别,备忘录模式可以单步回档
dispatch_suspend与dispatch_resume
定义如下,用于执行和挂起dispatch_object_t
void
dispatch_resume(dispatch_object_t object); // 执行
void
dispatch_suspend(dispatch_object_t object); // 挂起
注意:
处于非激活态的队列,直接调用dispatch_resume运行时会crash
演示:
dispatch_queue_t concurrentqueue = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_suspend(concurrentqueue);
dispatch_async(concurrentqueue, ^{
NSLog(@"任务执行完毕");
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_resume(concurrentqueue);
});
NSLog(@"代码执行到这里");
输出:
2021-08-19 20:32:24.400530+0800 GCDDemo[3364:1742868] 代码执行到这里
2021-08-19 20:32:29.890087+0800 GCDDemo[3364:1742884] 任务执行完毕
使用场景:
可以用于支持一组任务的暂停继续操作,例如多线程下载大文件,当然正在执行的任务是无法取消的,理论上也不允许,会有很多内存方面的问题
dispatch_wait、dispatch_notify、dispatch_cancel、dispatch_testcancel
定义如下,会根据object的类型映射成子类型的函数
intptr_t
dispatch_wait(void *object, dispatch_time_t timeout);
void
dispatch_notify(void *object, dispatch_object_t queue,
dispatch_block_t notification_block);
void
dispatch_cancel(void *object);
intptr_t
dispatch_testcancel(void *object);
映射关系:
dispatch_wait前两个会阻塞当前线程,第三个执行后小于0阻塞当前线程
dispatch_block_t:dispatch_block_wait
dispatch_group_t:dispatch_group_wait
dispatch_semaphore_t:dispatch_semaphore_wait
dispatch_notify一组任务执行完毕后调用
dispatch_block_t:dispatch_block_notify
dispatch_group_t:dispatch_group_notify
dispatch_cancel用于取消没有执行的任务
dispatch_block_t:dispatch_block_cancel
dispatch_source_t:dispatch_source_cancel
dispatch_testcancel检测任务是否被取消
dispatch_block_t:dispatch_block_testcancel
dispatch_source_t:dispatch_source_testcancel
网友评论