GCD 多线程 初探
GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用。所以说,结合block实现的GCD,把函数闭包( Closure )的特性发挥得淋漓尽致。
dispatch队列的生成可以有这几种方式:
1. dispatch_queue_t queue = dispatch_queue_create ( "com.dispatch.serial" ,DISPATCH_QUEUE_SERIAL ); //生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。
2. dispatch_queue_t queue = dispatch_queue_create ("com.dispatch.concurrent" , DISPATCH_QUEUE_CONCURRENT ); //生成一个并发执行队列,block被分发到多个线程去执行
3. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //获得程序进程缺省产生的并发队列,可设定优先级来选择高、中、低三个优先级队列。由于是系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断。需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。
官网文档解释说共有三个并发队列,但实际还有一个更低优先级的队列,设置优先级为 DISPATCH_QUEUE_PRIORITY_BACKGROUND 。Xcode调试时可以观察到正在使用的各个dispatch队列。
4. dispatch_queue_t queue = dispatch_get_main_queue(); //获得主线程的dispatch队列,实际是一个串行队列。同样无法控制主线程dispatch队列的执行继续或中断。
接下来我们可以使用dispatch_async或dispatch_sync函数来加载需要运行的block。
dispatch_async(queue, ^{
//block具体代码
}); //异步执行block,函数立即返回
dispatch_sync(queue, ^{
//block具体代码
}); //同步执行block,函数不返回,一直等到block执行完毕。编译器会根据实际情况优化代码,所以有时候你会发现block其实还在当前线程上执行,并没用产生新线程。
实际编程经验告诉我们,尽可能避免使用dispatch_sync,嵌套使用时还容易引起程序死锁。
如果queue1是一个串行队列的话,这段代码立即产生死锁:
dispatch_sync (queue1, ^{
dispatch_sync (queue1, ^{
......
});
......
});
那实际运用中,一般可以用dispatch这样来写,常见的网络请求数据多线程执行模型:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//子线程中开始网络请求数据
//更新数据模型
dispatch_sync(dispatch_get_main_queue(), ^{
//在主线程中更新UI代码
});
});
程序的后台运行和UI更新代码紧凑,代码逻辑一目了然。
dispatch队列是线程安全的,可以利用串行队列实现锁的功能。比如多线程写同一数据库,需要保持写入的顺序和每次写入的完整性,简单地利用串行队列即可实现:
dispatch_queue_t queue1 = dispatch_queue_create ("com.dispatch.writedb" , DISPATCH_QUEUE_SERIAL );
- (void)writeDB:(NSData *)data
{
dispatch_sync(queue1, ^{
//write database
});
}
下一次调用writeDB:必须等到上次调用完成后才能进行,保证writeDB:方法是线程安全的。
dispatch队列还实现其它一些常用函数,包括:
void dispatch_apply( size_t iterations, dispatch_queue_t queue, void (^block)( size_t )); //重复执行block,需要注意的是这个方法是同步返回,也就是说等到所有block执行完毕才返回,如需异步返回则嵌套在dispatch_async中来使用。多个block的运行是否并发或串行执行也依赖queue的是否并发或串行。
void dispatch_barrier_async( dispatch_queue_t queue, dispatch_block_tblock); //这个函数可以设置同步执行的block,它会等到在它加入队列之前的block执行完毕后,才开始执行。在它之后加入队列的block,则等到这个block执行完毕后才开始执行。
void dispatch_barrier_sync( dispatch_queue_t queue, dispatch_block_t block); //同上,除了它是同步返回函数
void dispatch_after( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); //延迟执行block
最后再来看看dispatch队列的一个很有特色的函数:
void dispatch_set_target_queue( dispatch_object_t object, dispatch_queue_tqueue);
它会把需要执行的任务对象指定到不同的队列中去处理,这个任务对象可以是dispatch队列,也可以是dispatch源(以后博文会介绍)。而且这个过程可以是动态的,可以实现队列的动态调度管理等等。比如说有两个队列dispatchA和dispatchB,这时把dispatchA指派到dispatchB:
dispatch_set_target_queue(dispatchA, dispatchB);
那么dispatchA上还未运行的block会在dispatchB上运行。这时如果暂停dispatchA运行:
dispatch_suspend(dispatchA);
则只会暂停dispatchA上原来的block的执行,dispatchB的block则不受影响。而如果暂停dispatchB的运行,则会暂停dispatchA的运行。
这里只简单举个例子,说明dispatch队列运行的灵活性,在实际应用中你会逐步发掘出它的潜力
GCD 多线程 初探的更多相关文章
- iOS开发——GCD多线程详解
GCD多线程详解 1. 什么是GCD Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,简单来说,GCD就是iOS一套解决多线程的机制,使用GCD能够最大限度简化多线程 ...
- GCD多线程的一个全面的题目
GCD多线程的一个全面的题目
- 【转】C++ 11 并发指南一(C++ 11 多线程初探)
引言 C++ 11自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些C++ 11的新特性,算是记录一下自己学到的东西吧,和大家共勉. 相信Linux程序员都用过Pthrea ...
- [Xcode 实际操作]八、网络与多线程-(22)使用GCD多线程技术异步下载图片
目录:[Swift]Xcode实际操作 本文将演示如何使用使用GCD多线程技术异步下载图片. Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法 ...
- Object-C关于GCD多线程的使用
```objc1 使用Crearte函数创建的并发队列和全局并发队列的主要区别: 1)全局并发队列在整个应用程序中本身是默认存在的并且对应有高优先级.默认优先级.低优先级和后台优先级一共四个并发队列, ...
- iOS开发——多线程篇——NSOperation(基于GCD多线程编程),下载图片并合成新图片
一.NSOperation的基本概念1.简介NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperatio ...
- ios 使用GCD 多线程 教程
什么是GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法.该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中.GCD ...
- ios开发:GCD多线程
ios有三种多线程编程技术,分别是NSThread,Cocoa NSOperation和GCD,GCD全称Grand Central Dispatch 是Apple开发的一个多核编程的解决方法,在iO ...
- GCD多线程
GCD本质线程自动管理指令包 GCD优点: 1.GCD 本身自带有线程锁的效果,能通过推迟昂贵计算任务并在后台运行它们来改善应用的响应性能. 2.GCD 提供了更易于使用的并发模型(效果方面类似于对锁 ...
随机推荐
- MongoDB安装、管理工具、操作
1. mongoDB安装.启动.关闭 1.1 下载安装包 wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.3.tgz 1.2 ...
- Hadoop学习(4)-- MapReduce
MapReduce是一种用于大规模数据集的并行计算编程模型,由Google提出,主要用于搜索领域,解决海量数据的计算问题.其主要思想Map(映射)和Reduce(规约)都是从函数是编程语言中借鉴而来的 ...
- tomcat 6.0.44 “has failed to stop it. This is very likely to create a memory leak” 问题调查
1. 问题起因 我们项目中缓存模块某个实现采用了ehcache(2.4.3),当项目部署到tomcat中后,对tomcat做停止服务操作(点击eclipse的console红色的停止按钮,奇怪的是有小 ...
- Oracle 10046 trace文件分析
生成10046 trace文件: SQL> create table t10046 as select * from dba_objects; Table created. SQL> se ...
- iOS 延迟执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), ...
- PostgreSQL Replication之第十章 配置Slony(4)
10.4 部署DDLs 对于生产性的应用程序来说,仅仅复制一个表明显是不够的.此外,通过没有办法保证数据从来不会发生改变.在某些时候,部署变化的数据结构(所谓的DDLs)是必要的. 现在的问题是,Sl ...
- linux第9天 UDP
今天学了一点UDP知识,还是IP协议.都不是重点,重点是socket服务器框架 不过还是把今天学的东西,先罗列出来,将来复习的时候方便 q UDP报文可能会丢失.重复 q UDP报文可能会乱序 q ...
- bzoj4216 Pig
水题,题目难点大概就是空间限制上了,开longlong会爆,可以开个int数组求前缀和,然后一旦绝对值超过20亿,则将其取模,并记录下当前位置,这样询问时就可以二分这些超过的位置,将其乘以20亿后加上 ...
- UVALive 7148 LRIP【树分治+线段树】
题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...
- windows系统调用 线程创建
#include "windows.h" #include "iostream" using namespace std; class CWorkerThrea ...