Grand Central Dispatch (GCD) 用法详细介绍

2024-05-30 15:18

本文主要是介绍Grand Central Dispatch (GCD) 用法详细介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. Dispatch Queue

执行处理有两种Dispatch Queue。
一种是等待现在执行中的处理的Serial Dispatch Queue。(顺序执行)
另一种是不等待现在执行中处理的Concurrent Dispatch Queue。(并行执行)

Concurrent Dispatch Queue执行:
线程0线程1线程2线程3
blk0blk1blk2blk3
blk5blk6blk4 
blk7   


2. dispatch_queue_create
通过 dispatch_queue_create 函数可以生成 Dispathch Queue。

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // 第一个参数为queue署名。第二个参数为创建的queue类型。null默认为Serial dispatch queue  
  2. dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, NULL);  
  3.   
  4. // dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, DIDPATCH_QUEUE_CONCURRENT);  
  5.   
  6. dispatch_async(myDispatchQueue, ^{ NSLog(@“ block on queue “); });  
  7.   
  8. // 结束后需要release  
  9. dispatch_release(myDispatchQueue);  
  10.   
  11. // 相应的有retain函数  
  12. // dispatch_retain(myDispatchQueue);  

虽然一执行完 dispatch_async 后里面释放queue,但是由于Block持有该Dispatch Queue,所以此处release后 queue 不会被废弃。


3. Main Dispatch Queue 和 Global Dispatch Queue
以上两种为系统标准提供的Dispatch Queue;

名称Dispatch Queue种类说明
Main Dispatch QueueSerial Dispatch Queue主线程执行
DISPATCH_QUEUE_PRIORITY_HIGHConcurrent Dispatch Queue高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULTConcurrent Dispatch Queue默认优先级
DISPATCH_QUEUE_PRIORITY_LOWConcurrent Dispatch Queue低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUNDConcurrent Dispatch Queue后台执行

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // 获取主线程  
  2. dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();  
  3.   
  4. //   
  5. dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);  
  6.   
  7. //   
  8. dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  9.   
  10. //   
  11. dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);  
  12.   
  13. //   
  14. dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);  

注:dispatch_retain() 和 dispatch_release() 对于这两种queue不会引起任何变化。


4. dispatch_set_target_queue
dispatch_queue_create() 函数生成的无论是Serial 还是 Concurrent ,都是默认优先级。
使用 dispatch_set_target_queue 可以变更优先级。
例如:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, NULL);  
  2. dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);  
  3. dispatch_set_target_queue(myDispatchQueue, globalDispatchQueueBackground);  

以上代码将 myDispatchQueue 的优先级变更为 后台优先级。


5. dispatch_after
想要在指定时间后执行处理,可使用 dispatch_after。
例如:3秒后将指定的Block 追加奥 Main Dispatch Queue 中。

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 33ull * NSEC_PER_SEC);  
  2. dispatch_after(time, dispatch_get_main_queue(), ^{ NSLog(@“waited at least three seconds.”); });  

注: dispatch_after 函数并不是在指定时间后执行处理,而是在指定时间后追加处理到Dispatch Queue。例如Main Dispatch Queue在主线程的RunLoop中执行。所以在比如每隔1/60秒执行的RunLoop,Block最快在3秒后执行,最慢在 3+1/60秒后执行。


6. Dispatch Group
如果想要在追加到多个Dispatch Queue中的多个处理全部结束后执行结束处理,,可使用Dispatch Group。
例如:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_group_t group = dispatch_group_create();  
  3.   
  4. dispatch_group_async(group, queue, ^{NSLog(@“bll0”);});  
  5. dispatch_group_async(group, queue, ^{NSLog(@“bll1”);});  
  6. dispatch_group_async(group, queue, ^{NSLog(@“bll2”);});  
  7.   
  8. dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@“done”); });  
  9. dispatch_release(group);  


其中可以使用 dispatch_group_wait函数仅等待全部处理执行结束:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_group_t group = dispatch_group_create();  
  3.   
  4. dispatch_group_async(group, queue, ^{NSLog(@“bll0”);});  
  5. dispatch_group_async(group, queue, ^{NSLog(@“bll1”);});  
  6. dispatch_group_async(group, queue, ^{NSLog(@“bll2”);});  
  7.   
  8. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);  
  9. dispatch_release(group);   

注:dispatch_group_wait 的返回值为0,标识全部处理执行结束;
返回值不为0,表示经过了指定时间,属于Dispatch Group 的某一个处理还在执行中;
由于 DISPATCH_TIME_FOREVER 标识永久等待,故而返回值恒为0;

dispatch_group_wait 可能会造成当前线程停止,直至所有处理执行结束。

7. dispatch_barrier_async
在多个并行处理之间插入指定处理后再继续多个并行处理。
例如:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_queue_create(“com.example.queue”, DISPATCH_QUEUE_CONCURRENT);  
  2.   
  3. dispatch_async(queue, blk0_for_reading);   
  4. dispatch_async(queue, blk1_for_reading);   
  5. dispatch_async(queue, blk2_for_reading);   
  6. dispatch_async(queue, blk3_for_reading);   
  7. dispatch_barrier_async(queue, blk_for_writing);  
  8. dispatch_async(queue, blk4_for_reading);   
  9. dispatch_async(queue, blk5_for_reading);   
  10. dispatch_async(queue, blk6_for_reading);   
  11. dispatch_async(queue, blk7_for_reading);   
  12. dispatch_async(queue, blk8_for_reading);   
  13.   
  14. dispatch_release(queue);  

使用 Concurrent Dispatch Queue 和 dispatch_barrier_async 可实现高效率的数据库访问和文件访问。


8. dispatch_apply
该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。
例如:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_apply(5, queue, ^(size_t index){ NSLog(@“%zu”, index); });  
  3. NSLog(@“done”);  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // 运行结果  
  2. 4  
  3. 1  
  4. 0  
  5. 3  
  6. 2  
  7. done  


9. dispatch_suspend / dispatch_resume
当追加大量处理到Dispatch Queue时,在追加处理的过程中,希望不执行一追加的处理,例如验算结果被Block截获时,一些处理会对这个演算结果造成影响。
可使用以上两个函数挂起和恢复queue。


10. Dispatch Semaphore
该函数是比 dispatch_barrier_async() 更细粒度的排他控制。
先看一下例子:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. NSMutableArray *array = [[NSMutableArray alloc] init];  
  3. for(int i = 0; i< 100000; ++i)  
  4. {  
  5.      dispatch_async(queue, ^{ [array addObject:[NSNumber numberWithInt:i]]; });  
  6. }  


以上代码执行后由内存错误导致应用异常结束的概率很高。
Dispatch Semaphore 是持有计数的信号。当计数为0时,表示等待;计数为1或者大于1时,减去1而不等待;

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // 生成函数,计数初始值为1  
  2. dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);  
  3.   
  4. // 一直等待,直到Dispatch Semaphore 的计数值达到大于等于1;  
  5. long result = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);  
  6. if (result == 0)  
  7. {  
  8.      // 可执行其他需要进行排他控制的处理  
  9. }else{  
  10.      // 在达到指定时间为止待机  
  11. }  

修改后的例子:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. // 保证可访问NSMutableArray 的线程同时只能有一个  
  3. dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);  
  4.   
  5. NSMutableArray *array = [[NSMutableArray alloc] init];  
  6. for(int i = 0; i< 100000; ++i)  
  7. {  
  8.      dispatch_async(queue, ^{   
  9.           dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);  
  10.           [array addObject:[NSNumber numberWithInt:i]];   
  11.      });  
  12. }   
  13. dispatch_release(semaphore);  


11. dispatch_once
dispatch_once 函数保证在应用程序执行中只执行一次指定处理的API;
例如:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int initialized = NO;  
  2. if (initialized == NO)  
  3. {  
  4.      //initialized  
  5.      initialized = YES;  
  6. }  


可转变成:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static dispatch_once_t pred;  
  2. dispatch_once(&pred, ^{  
  3.      //initialized  
  4. });  


原文地址:http://blog.csdn.net/mad2man/article/details/21786251

这篇关于Grand Central Dispatch (GCD) 用法详细介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016433

相关文章

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

JavaScript Array.from及其相关用法详解(示例演示)

《JavaScriptArray.from及其相关用法详解(示例演示)》Array.from方法是ES6引入的一个静态方法,用于从类数组对象或可迭代对象创建一个新的数组实例,本文将详细介绍Array... 目录一、Array.from 方法概述1. 方法介绍2. 示例演示二、结合实际场景的使用1. 初始化二

通过Docker Compose部署MySQL的详细教程

《通过DockerCompose部署MySQL的详细教程》DockerCompose作为Docker官方的容器编排工具,为MySQL数据库部署带来了显著优势,下面小编就来为大家详细介绍一... 目录一、docker Compose 部署 mysql 的优势二、环境准备与基础配置2.1 项目目录结构2.2 基

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语