【读书笔记】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多线程和内存管理》

时间: 2024-10-13 17:46:03

【读书笔记】GCD-API的相关文章

iOS 读书笔记-网络API

文章来自<ios网络高级编程> 在这里只是摘录,其中还有好多东西不知道是什么,等做完整本书的笔记回过头来看下. 框架的每一层都提供了一套关键api,为开发者提供了各种功能与控制. 1 nsurlconnection 是cocoa级别的api,它提供了简单的方法来加载url请求,可以与web service直接进行交互.获取图片.视频还能简单的得到一个格式化的html文档.它构建在NSStream之上,并且在http.https.文件和ftp进行了优化.NSURLConnection限制了你所使

《Spring实战》读书笔记--使用SpringMVC构建REST API

<Spring实战>读书笔记--使用SpringMVC构建REST API 1. REST介绍 REST(Representational State Transfer):表述性状态转移,是基于HTTP.URI.MIME(HTML.JSON等)协议的Web软件架构.它不同于SOAP Web服务(RPC)关注处理,面向行为,其更关注要处理的数据,面向资源. 1.1 <Spring实战>中是这样描述REST的: 为了理解REST是什么,我们将它的首字母缩写才拆分为不同的构成部分: 表述

Hadoop读书笔记(七)MapReduce 0.x版本API使用demo

Hadoop读书笔记(一)Hadoop介绍:http://blog.csdn.net/caicongyang/article/details/39898629 Hadoop读书笔记(二)HDFS的shell操作:http://blog.csdn.net/caicongyang/article/details/41253927 Hadoop读书笔记(三)Java API操作HDFS:http://blog.csdn.net/caicongyang/article/details/41290955

Hadoop读书笔记(三)Java API操作HDFS

Hadoop读书笔记(一)Hadoop介绍:http://blog.csdn.net/caicongyang/article/details/39898629 Hadoop读书笔记(二)HDFS的shell操作:http://blog.csdn.net/caicongyang/article/details/41253927 JAVA URL 操作HDFS OperateByURL.java package hdfs; import java.io.InputStream; import jav

《基于Android的读书笔记api》

1.     系统的需求分析 1.1系统目标 目本程序旨在开发一款简单实用.易操作的一款读书笔记软件. 1.2功能需求 该记事本软件应该具有以下功能: (1)登录 (2)书籍分类管理 (3)书籍管理 (4)我的读书笔记 (5)汇总每个用户的笔记数量 (6)统计某一个用户的每一本书的笔记数量 2.     系统的概要设计 该软件是一款是基于Android开发的手机应用,简单实用,易于上手. 2.1    运行环境 1.Android手机或平板电脑:主频在1Ghz及以上,内存为1GB以上,系统版本为

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记 这本书年初刷完,感觉不错,介绍了很多小点,都是平日不怎么关注的. 第1章 熟悉Objective-C 这章没什么好介绍 第1条:了解Objective-C语言的起源 第2条:在类的头文件中尽量少引入其他头文件 第3条:多用字面量语法,少用与之等价的方法 第4条:多用类型常量,少用#define预处理指令 要理解为啥要少用#define预处理指令. 然后具体用哪个, 自己定吧 第5条:用枚举表示状态.选项.状态

【转】《windows核心编程》读书笔记

这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入,但应该是合理的.开头几章由于我追求简洁,往往是很多单独的字句,后面的内容更为连贯. 海量细节. 第1章    错误处理 1.         GetLastError返回的是最后的错误码,即更早的错误码可能被覆盖. 2.         GetLastError可能用于描述成功的原因(CreatEvent)

《大型网站技术架构》读书笔记之六:永无止境之网站的伸缩性架构

此篇已收录至<大型网站技术架构>读书笔记系列目录贴,点击访问该目录可获取更多内容. 首先,所谓网站的伸缩性,指不需要改变网站的软硬件设计,仅仅通过改变部署的服务器数量就可以扩大或者缩小网站的服务处理能力.在整个互联网行业的发展渐进演化中,最重要的技术就是服务器集群,通过不断地向集群中添加服务器来增强整个集群的处理能力. 一.网站架构的伸缩性设计 1.1 不同功能进行物理分离实现伸缩 (1)纵向分离:将业务处理流程上得不同部分分离部署,实现系统的伸缩性: (2)横向分离:将不同的业务模块分离部署

TJI读书笔记15-持有对象

body, td { font-family: 微软雅黑; font-size: 10pt; } TJI读书笔记15-持有对象 总览 类型安全和泛型 Collection接口 添加元素 List 迭代器 LinkedList 栈 Set Map Queue Collection和Iterator Foreach与迭代器 总结 总览 It's a fairly simple program that only has a fixed quantity of objects with known l

读书笔记打一章

读书笔记第一章安卓是免费的,任何人都可以利用安卓的源代码定制完全属于自己的嵌入式系统,这极大地促进了安卓的发展,但是想要在各种设备上运行安卓系统,需要为各种设备定制安卓系统,这就叫做安卓系统的移植.安卓系统架构分为四层:1.Linux内核 2.C/C++代码库 3.Android SDK API 4.应用程序.安卓系统移植的主要工作:除了移植CPU之外,最重要的就是移植Linux驱动,还要增加一个抽象层.Linux内核版本:目前主要有三个:Linux2.4.Linux2.6.Linux3.x,而