近期在梳理多线程的知识点,那就先把系统API全部重新看下.
1. void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
//在一个调度队列里面,提交一个异步执行的block
2. void dispatch_async_f(dispatch_queue_t queue,void *_Nullable context,dispatch_function_t work);
//在一个调度队列里面提交一个异步执行的函数
这个函数不经常用,看API解释
* @param context
* The application-defined context parameter to pass to the function.
*
* @param work
* The application-defined function to invoke on the target queue. The first
* parameter passed to this function is the context provided to
* dispatch_async_f().
* The result of passing NULL in this parameter is undefined.
typedef void (*dispatch_function_t)(void *_Nullable);
queue不要为NULL,work不要为NULL,context是传参给work这个function,实验下.
- (void)testOne{
dispatch_async_f(dispatch_get_global_queue(0, 0),(__bridge void * _Nullable)(@(9)),test);
}
void test(void *context) {
NSLog(@"%@", context);
}
这个传参比较坑,必须是对象类型,刚开始测的时候用的是整型(int)数据的地址如,
int a,传参填的是&a,但是这样打印不是想要的结果,尝试如上解决,如果你可以用这种方式传参,请告诉我方法
3.dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
//在一个队列里,提交一个同步执行的block
4.dispatch_sync_f(dispatch_queue_t queue,void *_Nullable context,dispatch_function_t work);
//参考2
5. void dispatch_apply(size_t iterations, dispatch_queue_t queue,DISPATCH_NOESCAPE void (^block)(size_t));
这个函数没怎么用过,那我们看源码吧
void dispatch_apply(size_t iterations, dispatch_queue_t dq, void (^work)(size_t))
{
dispatch_apply_f(iterations, dq, work,
(dispatch_apply_function_t)_dispatch_Block_invoke(work));
}
void dispatch_apply_f(size_t iterations, dispatch_queue_t dq, void *ctxt,
void (*func)(void *, size_t))
{
if (unlikely(iterations == 0)) {
return;
}
dispatch_thread_context_t dtctxt =
_dispatch_thread_context_find(_dispatch_apply_key);
size_t nested = dtctxt ? dtctxt->dtc_apply_nesting : 0;
dispatch_queue_t old_dq = _dispatch_queue_get_current();
if (likely(dq == DISPATCH_APPLY_AUTO)) {
dq = _dispatch_apply_root_queue(old_dq);
}
dispatch_qos_t qos = _dispatch_priority_qos(dq->dq_priority);
if (unlikely(dq->do_targetq)) {
// if the queue passed-in is not a root queue, use the current QoS
// since the caller participates in the work anyway
qos = _dispatch_qos_from_pp(_dispatch_get_priority());
}
int32_t thr_cnt = (int32_t)_dispatch_qos_max_parallelism(qos,
DISPATCH_MAX_PARALLELISM_ACTIVE);
if (likely(!nested)) {
nested = iterations;
} else {
thr_cnt = nested < (size_t)thr_cnt ? thr_cnt / (int32_t)nested : 1;
nested = nested < DISPATCH_APPLY_MAX && iterations < DISPATCH_APPLY_MAX
? nested * iterations : DISPATCH_APPLY_MAX;
}
if (iterations < (size_t)thr_cnt) {
thr_cnt = (int32_t)iterations;
}
struct dispatch_continuation_s dc = {
.dc_func = (void*)func,
.dc_ctxt = ctxt,
.dc_data = dq,
};
dispatch_apply_t da = (typeof(da))_dispatch_continuation_alloc();
da->da_index = 0;
da->da_todo = iterations;
da->da_iterations = iterations;
da->da_nested = nested;
da->da_thr_cnt = thr_cnt;
#if DISPATCH_INTROSPECTION
da->da_dc = _dispatch_continuation_alloc();
*da->da_dc = dc;
#else
da->da_dc = &dc;
#endif
da->da_flags = 0;
if (unlikely(dq->dq_width == 1 || thr_cnt <= 1)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
}
if (unlikely(dq->do_targetq)) {
if (unlikely(dq == old_dq)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
} else {
return dispatch_sync_f(dq, da, _dispatch_apply_redirect);
}
}
dispatch_thread_frame_s dtf;
_dispatch_thread_frame_push(&dtf, dq);
_dispatch_apply_f2(dq, da, _dispatch_apply_invoke);
_dispatch_thread_frame_pop(&dtf);
}
这是一个同步队列的循环,必须等到这个队列执行完毕才会跳出循环,这个循环不是按顺序执行的.
void dispatch_apply_f(size_t iterations, dispatch_queue_t queue,void *_Nullable context,void (*work)(void *_Nullable, size_t));
//参考以上内容分析,不做解释
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
//队列执行优先级
dispatch_queue_attr_make_initially_inactive(dispatch_queue_attr_t _Nullable attr);
dispatch_queue_attr_make_with_autorelease_frequency(dispatch_queue_attr_t _Nullable attr,dispatch_autorelease_frequency_t frequency);
dispatch_qos_class_t
/*
__QOS_ENUM(qos_class, unsigned int,
QOS_CLASS_USER_INTERACTIVE
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
QOS_CLASS_USER_INITIATED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
QOS_CLASS_DEFAULT
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
QOS_CLASS_UTILITY
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
QOS_CLASS_BACKGROUND
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
QOS_CLASS_UNSPECIFIED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
);
*/
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_create函数。
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);
//创建队列
dispatch_queue_create(const char *_Nullable label,dispatch_queue_attr_t _Nullable attr);
//创建队列,attr值为DISPATCH_QUEUE_SERIAL,DISPATCH_QUEUE_CONCURRENT
dispatch_queue_get_label(dispatch_queue_t _Nullable queue);
//得到指定队列的标签,没有设定返回NULL
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);
//给GCD对象设置目标队列,这个目标队列负责处理这个对象。
//https://www.cnblogs.com/denz/archive/2016/02/24/5214297.html
void dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
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);
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-1");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-2");
});
dispatch_barrier_async(concurrentQueue, ^(){
NSLog(@"dispatch-barrier");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-3");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-4");
});
dispatch_barrier_async 作用是在并行队列中,等待前面两个操作并行操作完成,这里是并行输出
dispatch-1,dispatch-2
然后执行
dispatch_barrier_async中的操作,(现在就只会执行这一个操作)执行完成后,即输出
"dispatch-barrier,
最后该并行队列恢复原有执行状态,继续并行执行
dispatch-3,dispatch-4
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);
dispatch_barrier_sync和dispatch_barrier_async的区别
参考:通过GCD中的dispatch_barrier_(a)sync加强对sync中所谓等待的理解
void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key,void *_Nullable context, dispatch_function_t _Nullable destructor);
void *_Nullable dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);
void *_Nullable dispatch_get_specific(const void *key);
指定队列设置标识和取出标识
用法参考
主线程中也不绝对安全的 UI 操作
告诉你dispatch_queue_set_specific和dispatch_get_specific是个什么鬼
void dispatch_assert_queue(dispatch_queue_t queue);
void dispatch_assert_queue_barrier(dispatch_queue_t queue);
void dispatch_assert_queue_not(dispatch_queue_t queue);
//这三个没找到用法,我自己也没用过
参考:
GCD源码
Grand Central Dispatch和Block使用-浅析
dispatch_apply浅析-相关文章也很好
细说GCD如何用
GCD
iOS之多线程GCD-经典