zoukankan      html  css  js  c++  java
  • 【读书笔记】iOS-GCD-API

    一,Dispatch Queue

    dispatch_async(queue, ^{
            /*
             *想执行的任务
             */
            
        });

     

    其中queue分为两种:

    1,Serial Dispatch Queue 等待现在执行中处理结束。

    2,Concurrent Dispatch Queue 不等待现在执行中处理结束。

     

    二,dispatch_queue_create

    用于生成queue.

    1,生成Serial Dispatch Queue.

    dispatch_queue_t mySerialDispatchQueue=dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);

    2,生成Concurrent Dispatch Queue。

    dispatch_queue_t myConcurrentDispatchQueue=dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);

    3,用法

    dispatch_queue_t myConcurrentDispatchQueue=dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
        
    dispatch_async(myConcurrentDispatchQueue, ^{ NSLog(@"block on myConcurrentDispatchQueue"); });

     

    三,Main Dispatch Queue/Global Dispatch Queue

    1,Main Dispatch Queue. 

    在主线程中执行的Dispatch Queue.

    //Main Dispatch Queue的获取方法
        dispatch_queue_t mainDisaptchQueue=dispatch_get_main_queue()
        ;

     

    2,Global Dispatch Queue.

    在所有应用程序中都能够使用的Dispatch Queue.它有4个优先级。

    复制代码
    //Global Dispatch Queue的获取方法
        //高优先级
        dispatch_queue_t globalDispatchQueueHigh=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
        //默认优先级
        dispatch_queue_t globalDispatchQueueDefault=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //低优先级
        dispatch_queue_t globalDispatchQueueLow=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
        //后台优先级
        dispatch_queue_t globalDispatchQueueBackground=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    复制代码

    3,用法

    复制代码
    //在默认优先级的Global Dispatch Queue中执行block
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            /*
             *可并行执行的处理
             */
            dispatch_async(dispatch_get_main_queue(), ^{
                /*
                 *只能在主线程中执行的处理
                 */
                
            });
        });
    复制代码

     

    四,dispatch_set_target_queue

    用于变更Dispatch Queue的生成。

    //在后台执行动作处理的Serial Dispatch Queue的生成方法
        dispatch_queue_t mySerialDispatchQueue=dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
        dispatch_queue_t globalDispatchQueueBackground=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackground);

     

    五,dispatch_after

     指定时间后执行处理。

    1,ull是C语言的数值字面量,是显示表示类型时使用的字符串(表示“unsigned long long ”)。如果使用NSEC_PER_MSEC则可以以毫秒为单位计算。如果使用NSEC_PER_SEC则为毫微秒的数值。

    2,dispatch_time_t计算相对时间。dispatch_walltime用于计算绝对时间。

     

    在3秒后将指定的Block追加到Main Dispatch Queue.

    dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC);
        dispatch_after(time, dispatch_get_main_queue(), ^{
            NSLog(@"waited at least three seconds.");
        });
        

     

    六,Dispatch Group

    无论向什么样的Dispatch Queue中追加处理,使用Dispatch Group都可以监视这些处理执行的结束。一旦检测到所有执行结束,就可将结束的处理追加到Dispatch Queue中。这就是使用Dispatch Group的原因。

     

    1,追加3个Block到Global Dispatch Queue,这些Block如果全部执行完毕,就会执行Main Dispatch Queue中结束处理用的Block.

     

    复制代码
     //追加3个Block到Global Dispatch Queue,这些Block如果全部执行完毕,就会执行Main Dispatch Queue中结束处理用的Block.
        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, ^{
            NSLog(@"blk0");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"blk1");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"blk2");
        });
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"done");
        });
    复制代码

     

    2,在Dispatch Group中使用dispatch_group_wait函数等待全部处理执行结束。

    复制代码
     //在Dispatch Group中使用dispatch_group_wait函数等待全部处理执行结束。
        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, ^{
            NSLog(@"blk0");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"blk1");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"blk2");
        });
    
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    复制代码

     

     七,dispatch_barrier_async

    与Concurrent Dispatch Queue配合,dispatch)barrier_async函数可实现高效率的数据库访问和文件访问。

    1,用法。

    在blk_for_reading读操作后,加入写入处理。

    复制代码
     //blk3_for_reading后加入写入处理。
        //dispatch_barrier_async会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束之后,再将指定的处理追加到该Concurrent Dispatch Queue中。然后在由dispatch_barrier_async函数追加的处理执行完毕后,Concurrent Dispatch Queue才恢复为一般的动作。
        dispatch_queue_t queue=dispatch_queue_create("com.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, blk0_for_reading);
        dispatch_async(queue, blk1_for_reading);
        dispatch_async(queue, blk2_for_reading);
        dispatch_async(queue, blk3_for_reading);
        dispatch_barrier_async(queue, blk_for_writing);
        dispatch_async(queue, blk4_for_reading);
        dispatch_async(queue, blk5_for_reading);
        dispatch_async(queue, blk6_for_reading);
        dispatch_async(queue, blk7_for_reading);
    复制代码

    八,dispatch_sync

    “非同步”,容易形成死锁。

    三种死锁的情况:

    复制代码
    //dispatch_sync
        //死锁1
        dispatch_queue_t queue=dispatch_get_main_queue();
        dispatch_sync(queue, ^{
            NSLog(@"Hello?");
        });
        
        //死锁2
        dispatch_queue_t queue=dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
        dispatch_async(queue, ^{
            dispatch_sync(queue, ^{
                NSLog(@"Hello?");
            });
        });
        
        //死锁3
        dispatch_queue_t queue=dispatch_get_main_queue();
        dispatch_async(queue, ^{
            dispatch_sync(queue, ^{
                NSLog(@"Hello?");
            });
        });
    复制代码

     

    九,dispatch_apply.

    dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API。该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。

    用法:

    dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_apply(10, queue, ^(size_t index) {
            NSLog(@"%ld",index);
        });
        NSLog(@"done");

    十,dispatch_suspend/dispatch_resume.

    挂起后,追加到Dispatch Queue中但尚未执行的处理在此之后停止执行。而恢复则使得这些处理能够继续执行。

    用法:

     //将指定的Dispatch Queue挂起
        dispatch_suspend(queue);
        //将指定的Dispatch Queue恢复。
        dispatch_resume(queue);

    十一,Dispatch Semaphore.

    Dispatch Semaphore是持有计数的信号,该计数是多线程编程中的计数类型信号。所谓信号,类似于过马路时常用的

     手旗。而在Dispatch Semaphore中,使用计数来实现该功能。计数为0时等待,计数为1或大于1时,减去1而不等待。

    1,用法:

    复制代码
        dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);
        long result=dispatch_semaphore_wait(semaphore, time);
        if (result==0) {
            //计数为0时等待。
            //可进行需要进行排他控制的处理
        }else{
            //计数为1或大于1时,减去1而不等待。
        }
    复制代码

    2,其好处。

    原代码:

    复制代码
    //此代码使用Global Dispatch Queue更新NSMutableArray类对象,所以执行后由内存错误导致应用程序异常结束的概率很高。此时应使用Dispatch Semaphore.
        dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        NSMutableArray *array=[[NSMutableArray alloc]init];
        for (int i=0; i<10000; ++i) {
            dispatch_async(queue, ^{
                [array addObject:[NSNumber numberWithInt:i]];
            });
        }
    复制代码

    修改后代码:

    复制代码
        //修改后代码
        dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //Dispatch Semaphore的计数初始值设定为“1”。保证可访问NSMutableArray类对象的线程,同时只能有1个
        dispatch_semaphore_t semaphore=dispatch_semaphore_create(1);
        
        NSMutableArray *array=[[NSMutableArray alloc]init];
        for (int i=0; i<10000; ++i) {
            dispatch_async(queue, ^{
                //一直等待,直到Dispatch Semaphore的计数值达到大于等于1.
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                //Dispatch Semaphore的计数达到1后,开始减去1而不等待。此时,semaphore减去1变成0.
                [array addObject:[NSNumber numberWithInt:i]];
                //将semaphore的计数值加1.
                dispatch_semaphore_signal(semaphore);
            });
        }
    复制代码

     

    十二,dispatch_once。

    保证在应用程序执行中只执行一次指定处理的API。

    原代码:

    //原代码
        static int initialized=NO;
        if (initialized==NO) {
            //初始化
            initialized=YES;
        }

    修改后代码:

     //修改后代码
        static dispatch_once_t pred;
        dispatch_once(&pred, ^{
            //初始化
        });

     

    十三,Dispatch I/O。

    在读取较大文件时,如果将文件分成合适的大小并使用Global Dispatch Queue并列读取的话,应该会比一般的读取

    速度快不少。现在的输入/输出硬件已经可以做到一次使用多个线程更快地并列读取了。能实现这一功能的就是Dispatch I/O和Dispatch Data.

    用法:

    复制代码
     //通过Dispatch I/O读写文件时,使用Global Dispatch Queue将1个文件按某个大小read/write.
        dispatch_async(queue, ^{/*读取0~8191字节*/ });
        dispatch_async(queue, ^{/*读取8192~16383字节*/ });
        dispatch_async(queue, ^{/*读取16384~24575字节*/ });
        dispatch_async(queue, ^{/*读取24576~32767字节*/ });
        dispatch_async(queue, ^{/*读取32768~40959字节*/ });
        dispatch_async(queue, ^{/*读取40960~49151字节*/ });
        dispatch_async(queue, ^{/*读取49152~57343字节*/ });
        dispatch_async(queue, ^{/*读取57344~65535字节*/ });
    复制代码

     

     

    参考资料:《Objective-C高级编程 iOS与OS X多线程和内存管理》

  • 相关阅读:
    Kettle使用kettle.properties
    kettle 获取文件名
    连接池的补充设置,应用到上面所有数据源中
    kettle 获取某个目录下所有的文件
    不小心删库了怎么办,用binlog可以恢复
    江北的KETTLE学习日志
    Python3 中,bytes 和 str
    kettle入门(四) 之kettle取昨天时间&设置任意时间变量案例
    30-Day Leetcoding Challenge Day17(构造并查集)
    30-Day Leetcoding Challenge Day16
  • 原文地址:https://www.cnblogs.com/yang-guang-girl/p/4852038.html
Copyright © 2011-2022 走看看