美文网首页
GCD-DISPATCH-多线程

GCD-DISPATCH-多线程

作者: 沐时 | 来源:发表于2017-12-20 18:08 被阅读58次
近期在梳理多线程的知识点,那就先把系统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-经典

相关文章

  • GCD-DISPATCH-多线程

    近期在梳理多线程的知识点,那就先把系统API全部重新看下. void dispatch_barrier_async...

  • iOS多线程 NSOperation

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程 pthread、NSThread

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程: GCD

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程运用

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程基础

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • 多线程介绍

    一、进程与线程 进程介绍 线程介绍 线程的串行 二、多线程 多线程介绍 多线程原理 多线程的优缺点 多线程优点: ...

  • iOS进阶之多线程管理(GCD、RunLoop、pthread、

    深入理解RunLoopiOS多线程--彻底学会多线程之『GCD』iOS多线程--彻底学会多线程之『pthread、...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

网友评论

      本文标题:GCD-DISPATCH-多线程

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