美文网首页
dispatch_queue_t详解

dispatch_queue_t详解

作者: 野码道人 | 来源:发表于2021-08-20 16:34 被阅读0次

定义在queue.h中,队列相关结构和操作语义定义在其中,如下先看几个宏定义,用于创建不同类型的队列

DISPATCH_QUEUE_SERIAL 串行队列
DISPATCH_QUEUE_SERIAL_INACTIVE 非激活态串行队列
DISPATCH_QUEUE_CONCURRENT 并发队列
DISPATCH_QUEUE_CONCURRENT_INACTIVE 非激活态并发队列

  • 异步+block
void
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  • 异步+c函数指针
void
dispatch_async_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);
  • 同步+block
void
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  • 同步+c函数指针
void
dispatch_sync_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);
  • 在调度队列上同步执行,不会阻塞当前线程,相当对添加一个异步栅栏函数
void
dispatch_async_and_wait(dispatch_queue_t queue,
        DISPATCH_NOESCAPE dispatch_block_t block);
  • 功能与上面的相同block换成c函数指针
void
dispatch_async_and_wait_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

以上举例:

dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
NSInteger count = 10;
while (count--) {
    dispatch_async(concurrentQueue, ^{
        usleep(1000 * 1000); // 线程休眠一秒
        NSLog(@"dispatchObject %ld:执行完毕", (long)count);
    });
}
NSLog(@"0-------------:%@", [NSThread currentThread]);
dispatch_async_and_wait(concurrentQueue, ^{
    NSLog(@"async_and_wait:%@", [NSThread currentThread]);
    sleep(5);
});
NSInteger n = 10;
while (n--) {
    dispatch_async(concurrentQueue, ^{
        usleep(1000 * 1000); // 线程休眠一秒
        NSLog(@"dispatchObject %ld:执行完毕", (long)count);
    });
}
NSLog(@"1-------------:%@", [NSThread currentThread]);
NSLog(@"2-------------:%@", [NSThread currentThread]);

输出:

2021-08-20 14:06:25.803501+0800 GCDDemo[3657:1929186] 0-------------:<NSThread: 0x28389c940>{number = 1, name = main}
2021-08-20 14:06:25.803606+0800 GCDDemo[3657:1929186] async_and_wait:<NSThread: 0x28389c940>{number = 1, name = main}
2021-08-20 14:06:26.806324+0800 GCDDemo[3657:1929200] dispatchObject 1:执行完毕
2021-08-20 14:06:26.806327+0800 GCDDemo[3657:1929209] dispatchObject 0:执行完毕
2021-08-20 14:06:26.808548+0800 GCDDemo[3657:1929199] dispatchObject 9:执行完毕
2021-08-20 14:06:26.808601+0800 GCDDemo[3657:1929202] dispatchObject 8:执行完毕
2021-08-20 14:06:26.808674+0800 GCDDemo[3657:1929201] dispatchObject 6:执行完毕
2021-08-20 14:06:26.808681+0800 GCDDemo[3657:1929205] dispatchObject 7:执行完毕
2021-08-20 14:06:26.808723+0800 GCDDemo[3657:1929204] dispatchObject 5:执行完毕
2021-08-20 14:06:26.808733+0800 GCDDemo[3657:1929206] dispatchObject 4:执行完毕
2021-08-20 14:06:26.808779+0800 GCDDemo[3657:1929207] dispatchObject 3:执行完毕
2021-08-20 14:06:26.808783+0800 GCDDemo[3657:1929208] dispatchObject 2:执行完毕
2021-08-20 14:06:30.804395+0800 GCDDemo[3657:1929186] 1-------------:<NSThread: 0x28389c940>{number = 1, name = main}
2021-08-20 14:06:30.804676+0800 GCDDemo[3657:1929186] 2-------------:<NSThread: 0x28389c940>{number = 1, name = main}
2021-08-20 14:06:31.809710+0800 GCDDemo[3657:1929207] dispatchObject -1:执行完毕
2021-08-20 14:06:31.809794+0800 GCDDemo[3657:1929206] dispatchObject -1:执行完毕
2021-08-20 14:06:31.809984+0800 GCDDemo[3657:1929204] dispatchObject -1:执行完毕
2021-08-20 14:06:31.810001+0800 GCDDemo[3657:1929205] dispatchObject -1:执行完毕
2021-08-20 14:06:31.809710+0800 GCDDemo[3657:1929208] dispatchObject -1:执行完毕
2021-08-20 14:06:31.810123+0800 GCDDemo[3657:1929201] dispatchObject -1:执行完毕
2021-08-20 14:06:31.824242+0800 GCDDemo[3657:1929199] dispatchObject -1:执行完毕
2021-08-20 14:06:31.824286+0800 GCDDemo[3657:1929202] dispatchObject -1:执行完毕
2021-08-20 14:06:31.824423+0800 GCDDemo[3657:1929209] dispatchObject -1:执行完毕
2021-08-20 14:06:31.824453+0800 GCDDemo[3657:1929213] dispatchObject -1:执行完毕

结论:

以上代码在主线程执行,先提交了10个任务到队列,然后调用dispatch_async_and_wait,之后再添加10个任务到队列,输出结果如上,证明dispatch_async_and_wait会复用当前线程,并且在当前线程同步执行

  • 阻塞当前线程的迭代器,在指定队列上提交指定数量的任务,是否并发依赖于queue参数
void
dispatch_apply(size_t iterations,
        dispatch_queue_t DISPATCH_APPLY_QUEUE_ARG_NULLABILITY queue,
        DISPATCH_NOESCAPE void (^block)(size_t));
  • 功能与上面的相同block换成c函数指针
void
dispatch_apply_f(size_t iterations,
        dispatch_queue_t DISPATCH_APPLY_QUEUE_ARG_NULLABILITY queue,
        void *_Nullable context, void (*work)(void *_Nullable, size_t));
  • iOS6已废弃,原因是获取到的队列若是当前执行队列并且刚好需要同步提交时候会发生死锁
API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
dispatch_queue_t
dispatch_get_current_queue(void);
  • 获取主队列、获取全局并发队列
dispatch_queue_main_t
dispatch_get_main_queue(void)

dispatch_queue_global_t
dispatch_get_global_queue(intptr_t identifier, uintptr_t flags);
  • 用于设置队列初始非激活态的属性值
dispatch_queue_attr_t
dispatch_queue_attr_make_initially_inactive(
        dispatch_queue_attr_t _Nullable attr);```
  • 设置队列属性为自动释放频率frequency
dispatch_queue_attr_t
dispatch_queue_attr_make_with_autorelease_frequency(
        dispatch_queue_attr_t _Nullable attr,
        dispatch_autorelease_frequency_t frequency);
  • 设置队列属性QOS
dispatch_queue_attr_t
dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t _Nullable attr,
        dispatch_qos_class_t qos_class, int relative_priority);
  • 创建队列
dispatch_queue_t
dispatch_queue_create(const char *_Nullable label,
        dispatch_queue_attr_t _Nullable attr);
  • 根据目标队列target创建一个新的调度队列。
dispatch_queue_t
dispatch_queue_create_with_target(const char *_Nullable label,
        dispatch_queue_attr_t _Nullable attr, dispatch_queue_t _Nullable target)
        DISPATCH_ALIAS_V2(dispatch_queue_create_with_target);
  • 队列标签
const char *
dispatch_queue_get_label(dispatch_queue_t _Nullable queue);
  • 返回队列QOS
dispatch_qos_class_t
dispatch_queue_get_qos_class(dispatch_queue_t queue,
        int *_Nullable relative_priority_ptr);
  • 设置目标队列
void
dispatch_set_target_queue(dispatch_object_t object,
        dispatch_queue_t _Nullable queue);
  • iOS app无需调用
void
dispatch_main(void);
  • 延时执行block
void
dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
        dispatch_block_t block);
  • 延时执行c函数指针
void
dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);
  • 栅栏
void
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
void
dispatch_barrier_async_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);
void
dispatch_barrier_sync(dispatch_queue_t queue,
        DISPATCH_NOESCAPE dispatch_block_t block);
void
dispatch_barrier_sync_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);
void
dispatch_barrier_async_and_wait(dispatch_queue_t queue,
        DISPATCH_NOESCAPE dispatch_block_t block);
void
dispatch_barrier_async_and_wait_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

注意:

栅栏函数在主队列和全局并发队列是无效的
作用是强制设置执行顺序:pre-barrier->barrier->after-barrier
以上的区别是:
dispatch_barrier_async不会复用当前线程
dispatch_barrier_sync会复用当前线程
dispatch_barrier_async_and_wait会复用当前线程
因此并发队列下后两个会减小创建线程的开销,串行队列下栅栏函数毫无意义,因为本就是按序执行的,还容易造成死锁

  • 给队列绑定上下文和key
void
dispatch_queue_set_specific(dispatch_queue_t queue, const void *key,
        void *_Nullable context, dispatch_function_t _Nullable destructor);
  • 获取队列上下文和key
void
void *_Nullable
dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);
  • 通过key获取当前队列绑定的上下文
void *_Nullable
dispatch_get_specific(const void *key);

相关文章

网友评论

      本文标题:dispatch_queue_t详解

      本文链接:https://www.haomeiwen.com/subject/egqtiltx.html