一,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多线程和内存管理》

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

  1. 《程序员的自我修养》读书笔记——系统调用、API

        系统调用 程序运行的时候,本身是没有权限访问多少系统资源的.系统资源有限,如果操作系统不进行控制,那么各个程序难免会产生冲突.线程操作系统都将可能产生冲突的系统资源保护起来,阻止程序直接访问. ...

  2. [读书笔记]iOS 7 UI设计 对比度

    好久没写随笔了,最近在读<iOS 7 byTutorials>,很不错,推荐给大家. 每一个好的程序员也都是一个设计师,不懂设计的程序员不是好的CTO.哈哈,开个小玩笑. iOS 7设计的 ...

  3. 读书笔记-iOS核心动画高级技巧

    如果不使用+imageNamed:,那么把整张图片绘制到CGContext可能是最佳的方式了. 这里我们利用了CALayer的KVC来存储和检索任意的值,将图层和索引打标签. 使用KVC打标签

  4. 《Java 8实战》读书笔记系列——第三部分:高效Java 8编程(四):使用新的日期时间API

    https://www.lilu.org.cn/https://www.lilu.org.cn/ 第十二章:新的日期时间API 在Java 8之前,我们常用的日期时间API是java.util.Dat ...

  5. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  6. 《More Effective C#》读书笔记

    <More Effective C#>这本书,大概是四年前看完的,但只整理了一部分读书笔记,后面有时间的话,会陆续补充的. More Effective C# :使用泛型 More Eff ...

  7. 第一章 Andorid系统移植与驱动开发概述 - 读书笔记

    Android驱动月考1 第一章 Andorid系统移植与驱动开发概述 - 读书笔记 1.Android系统的架构: (1)Linux内核,Android是基于Linux内核的操作系统,并且开源,所以 ...

  8. TJI读书笔记15-持有对象

    TJI读书笔记15-持有对象 总览 类型安全和泛型 Collection接口 添加元素 List 迭代器 LinkedList 栈 Set Map Queue Collection和Iterator ...

  9. WPF,Silverlight与XAML读书笔记第四十三 - 多媒体支持之文本与文档

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. Glyphs对象(WPF,Silverlig ...

  10. 《深入理解bootstrap》读书笔记:第一章 入门准备

    一.bootstrap框架简介 Bootstrap是最流行的前端开发框架. 什么是框架:开发过程的半成品. bootstrap具有以下重要特性: (1)完整的CSS样式插件 (2)丰富的预定义样式表 ...

随机推荐

  1. C#基础总结之二循环控制-运算符

    #region 第二天 作业2 从键盘上输入三个数,用if语句和逻辑表达式把最小数找出来. //需要:控制台输入 三个变量(a,b,c)判断这三个数其中一个最小的值 打印输出 //Console.Wr ...

  2. Java知多少(106)程序与数据库连接

    一个网络关系数据库应用系统是一个三层次结构.客户机与服务器采用网络连接,客户机端应用程序按通信协议与服务器端的数据库程序通信:数据库服务程序通过SQL命令与数据库管理系统通信. Java程序与数据库连 ...

  3. Linux高级编程--08.线程概述

    线程 有的时候,我们需要在一个基础中同时运行多个控制流程.例如:一个图形界面的下载软件,在处理下载任务的同时,还必须响应界面的对任务的停止,删除等控制操作.这个时候就需要用到线程来实现并发操作. 和信 ...

  4. codeforce No to Palindromes!(枚举)

    /* 题意:给定一个字符串中没有任何长度>1的回文子串!求按照字典序的该串的下一个字符串 也不包含长度>1的任何回文子串! 思路:从最低位进行枚举,保证第i位 不与 第 i-1位和第 i- ...

  5. web.config中httpRunTime的属性

    配置httpRuntime也可以让FileUpload上传更大的文件,不过设置太大了会因用户将大量文件传递到该服务器而导致的拒绝服务攻击(属性有说明) <httpRuntime> < ...

  6. E:无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系

    安装terminator等一些软件等时候,遇到了这样等问题 leo@leo:~$ sudo apt-get install terminator [sudo] password for leo: 正在 ...

  7. sql server 脚本创建数据库邮件

    sql server 脚本创建数据库邮件代码: --脚本创建数据库邮件 --1.开启数据库邮件 RECONFIGURE WITH OVERRIDE GO RECONFIGURE WITH OVERRI ...

  8. [转]提高 Linux 上 socket 性能,加速网络应用程序的 4 种方法

    原文链接:http://www.ibm.com/developerworks/cn/linux/l-hisock.html 使用 Sockets API,我们可以开发客户机和服务器应用程序,它们可以在 ...

  9. [操作系统实验lab4]实验报告

    实验概况 在开始实验之前,先对实验整体有个大概的了解,这样能让我们更好地进行实验. 我们本次实验需要补充的内容包括一整套以sys开头的系统调用函数,其中包括了进程间通信需要的一些系统调用如sys_ip ...

  10. 6/19 sprint3 看板和燃尽图的更新