zoukankan      html  css  js  c++  java
  • GCD 多线程技术

     Grand Central Dispatch(GCD)是异步执行任务的技术之一。一般将应用程序中记述的线程管理用

    的代码在系统级中实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成

    必要的线程并计划执行任务。由于线程管理是作为系统的一部分来实现的,因此可以统一管理,也可以执行任务,

    这样就比以前的线程更有效率。

    GCD API 

    1. Dispatch Queue 队列

    队列有两种类型:

    Serial Dispatch Queue 串行队列,使用一个线程,按照追加的顺序(先进先出FIFO)执行处理。多个串行队列之间是并行处理的。
    Concurrent Dispatch Queue 并行队列,使用多个线程,并发处理

    2.diapatch_queue_create

    创建 Serial Queue:

    dispatch_queue_t mySerailQueue = dispatch_queue_create("com.r.dispatchSerailQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com.r.dispatchConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);

    第一个参数是指定 Serial dispatch queue 的名称。该名称在Xcode和Instruments的调试器中作为Dispatch Queue名称.

    第二个参数是生成Dispatch Queue的类型,如果是NULL 或者 DISPATCH_QUEUE_SERIAL生成串行队列,

    指定为DISPATCH_QUEUE_CONCURRENT生成并发队列.

    3.Main Dispatch Queue/Global Dispatch Queue

    获取系统标准提供的Dispatch Queue。

    Main Dispatch Queue是在主线程执行的dispatch queue, Main Dispatch Queue是一个Serail Dispatch Queue。追加到Main Dispatch Queue的处理在主线程的RunLoop中执行。一般将用户界面更新等必需要在主线程中执行的处理追加到Main Dispatch Queue中。

    Global Dispatch Queue是所有应用程序都能过使用的Concurrent Dispatch Queue。没有必要通过dispatch_queue_create函数逐个创建Concurrent Dispatch Queue,只要获取Global Dispatch Queue使用即可。Global Dispatch Queue有四个优先级

    名称Dispatch Queue的种类说明
    Main Dispatch Queue Serial Dispatch Queue 主线程执行
    Global Dispatch Queue(High Priority) Concurrent Dispatch queue 执行优先级:高(最高)
    Global Dispatch Queue(Default Priority) Concurrent Dispatch queue 执行优先级:默认
    Global Dispatch Queue(Low Priority) Concurrent Dispatch queue 执行优先级:低
    Global Dispatch Queue(Background Priority) Concurrent Dispatch queue 执行优先级:后台

    获取Dispatch Queue方法:

    dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
    
    dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    使用Main Dispatch Queue 和 Global Dispatch Queue

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            /**
             *  可并行处理的任务TODO
             */
    
            dispatch_async(dispatch_get_main_queue(), ^{
                /**
                 *  主线程执行
                 */
            });
        });
    
    

    4. dispatch_after

    dispatch_after表示在指定的时间之后追加处理到Dispatch Queue。并不是指定时间后执行处理。

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
            NSLog(@"等待3秒后执行");
     });

    虽然在有严格时间到要求下使用时会出现问题,但在大致延迟执行处理时,该函数还是有效的。

    5.dispatch_suspend/dispatch_resume

    当追加大量处理到Dispatch Queue时,在追加处理到过程中,有时希望不执行已追加的处理。在这种情况下只要挂起Dispatch Queue即可。

    dispatch_suspend 函数挂起指定的Dispatch Queue

    dispatch_resume 函数恢复指定的Dispatch Queue

    这些函数对已经执行的处理没有影响,挂起后,追加到Dispatch Queue中处理在此之后暂停执行,而恢复使得这些处理继续执行。

    6.Dispatch Group

    在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理.

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
            for (int i=0; i<2000; i++) {
                NSLog(@"111111");
            }
        });
        dispatch_group_async(group, queue, ^{
            for (int i=0; i<2000; i++) {
                NSLog(@"2222222");
            }
        });
        dispatch_group_async(group, queue, ^{
            for (int i=0; i<2000; i++) {
                NSLog(@"33333");
            }
        });
        //最后执行4444
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"44444");
        });
        NSLog(@"555555");

    7. dispatch_barrier_async

       dispatch_async(queue, ^{
            //读文件
        });
        dispatch_async(queue, ^{
             //读文件
        });
    
        //使用dispatch_barrier_async避免数据竞争
        dispatch_barrier_async(queue, ^{
            //写文件
        });
        dispatch_async(queue, ^{
            //读文件
        });
        dispatch_async(queue, ^{
            //读文件
        });

    一个dispatch barrier 允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier, 他会延迟执行barrier的block,

    等待所有在barrier之前提交的blocks执行结束。 这时,barrier block自己开始执行。 之后, 队列继续正常的执行操作。

    调用这个函数总是在barrier block被提交之后立即返回,不会等到block被执行。当barrier block到并发队列的最前端,

    他不会立即执行。相反,队列会等到所有当前正在执行的blocks结束执行。到这时,barrier才开始自己执行。

    所有在barrier block之后提交的blocks会等到barrier block结束之后才执行

    这里指定的并发队列应该是自己通过dispatch_queue_create函数创建的。

    如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_async函数。

    8.dispatch_apply

    dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API。

    该函数按指定的次数将指定的Block追加到Dispatch Queue中,并等待全部处理执行结束。

    1 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    2     dispatch_apply(10, queue, ^(size_t index) {
    3         NSLog(@"%zu", index);//并行
    4     });
    5     //最后执行
    6     NSLog(@"11");

    9. Dispatch Semaphore

    信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理,则可告知系统按照我们指定的信号量数量来执行多个线程。

     1 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     2     
     3     /**
     4      * 生成Dispatch Semaphore
     5      * Dispatch Semaphore 的计数初始值设定为1
     6      * 保证可访问NSMutableArray类对象的线程同时只有一个
     7      */
     8     dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
     9     NSMutableArray *array = [[NSMutableArray alloc] init];
    10     
    11     for (int i=0; i<10000; i++) {
    12         dispatch_async(queue, ^{
    13             /**
    14              *  等待Dispatch Semaphore
    15                 一直等待,直到Dispatch Semaphore 的计数的值达到大于等于1
    16              */
    17             dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    18             
    19             /**
    20              *  由于Dispatch Semaphore 的计数达到大于等于1
    21              所以Dispatch Semaphore 的计数值减去1
    22              dispatch_semaphore_wait函数执行返回
    23              
    24              即执行到此时Dispatch Semaphore的计数值恒为00
    25              
    26              由于可访问NSMutableArray类对象的线程数只有1个
    27              因此可安全的进行更新
    28              */
    29             [array addObject:[NSNumber numberWithInt:i]];
    30             
    31             /**
    32              * 排他控制处理结束
    33              所以通过dispatch_semaphore_signal函数
    34              将DispatchSemaphore的计数值加1
    35              如果有通过dispatch_semaphore_wait函数
    36              等待Dispatch Semaphore的计数值增加的线程
    37              就由最先等待的线程执行。
    38              */
    39             dispatch_semaphore_signal(semaphore);
    40         });
    41     }
  • 相关阅读:
    WHERE col1=val1 AND col2=val2;index exists on col1 and col2, the appropriate rows can be fetched directly
    MySQL 交集 实现方法
    MBProgressHUD的使用
    Xcode4 使用 Organizer 分析 Crash logs(转)
    SimpleXML 使用详细例子
    PHP的XML Parser(转)
    iPhone,iPhone4,iPad程序启动画面的总结 (转)
    Pop3得到的Email 信件格式介绍
    yii总结
    隐藏Tabbar的一些方法
  • 原文地址:https://www.cnblogs.com/miaocunfa/p/9663592.html
Copyright © 2011-2022 走看看