文档章节

iOS GCD常用函数总结

董桉远
 董桉远
发布于 2014/04/19 15:58
字数 1049
阅读 2683
收藏 6
点赞 1
评论 2

GCD提供两种Dispatch Queue, 分别为Concurrent Dispatch Queue 和 Serial Dispatch Queue.

Serial Dispatch Queue 使用一个thread。

Concurrent Dispatch Queue 使用多个thread。

获取Dispatch Queue:

0)dispatch_queue_create

dispatch_queue_t queue = dispatch_queue_create("name.of.your.queue",NULL);
第一个参数为queue的名字,第二个参数传NULL表明要创建一个Serial Dispatch Queue, 传入DISPATCH_QUEUE_CONCURRENT 创建一个 Concurrent Dispatch Queue。

如果是对数据库表更新或更新文件,最好为每一个表或文件建立一个Serial Dispatch Queue,这样能保证只有一个thread会对数据进行更新。

如果对那些不会引起数据不一致问题的任务,需要放到Concurrent Dispatch Queue执行。

1)从Main Dispatch Queue/Global Dispatch Queue获取

//main queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();

//global queue of high priority
dispatch_queue_t globalHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);

//global queue of default priority
dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

//global queue of low priority
dispatch_queue_t globalLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);

//global queue of background priority
dispatch_queue_t globalBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
Main Dispatch Queue -> Serial dispatch queue

Global Dispatch Queue -> Concurrent dispatch queue

dispatch_set_target_queue: 主要用来给新建的queue设置优先级

dispatch_queue_t serialQueue = dispatch_queue_create("name.of.queue",NULL);

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

dispatch_set_target_queue(serialQueue, globalQueue);
需要注意的是,第一个参数是自定义的queue,而不是系统的queue。因为你不能给系统的queue设置权限。通过上面设置,serialQueue 就有了与globalQueue一样的优先级。其实这个函数不仅可以设置queue的优先级,还可以设置queue之间的层级结构。


dispatch_after: 过一段时间执行queue中的task

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

dispatch_after(time, dispatch_get_main_queue(),^{
               NSLog(@"after 3 seconds...");});

Dispatch Group

0)dispatch_group_notify

dispatch group 可以在group中的dispatch queue都执行完之后,通过一个dispatch_group_notify通知回调。

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(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"finished...");});

输出总会保证"finished..."会在最后一句输出。

1)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(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

dispatch_group_wait提供了一种类似超时的机制,当然如果等待时间设置为DISPATCH_TIME_FOREVER,功能和dispatch_group_notify是一样的。

dispatch_barrier_async

dispatch_barrier_async是一个可以让当前任务等待queue其他任务完成再执行的函数。例如,从数据库读取数据是可以多线程并发读取的,因为这样提高效率。但是,更新数据库数据,就要保证只有一个线程进行更新操作。所以,当更新操作发生的时候,一定要保证读操作和其他更新操作等待。

dispatch_queue_t queue = dispatch_queue_create("barrier.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, read_block_0);
dispatch_async(queue, read_block_1);
dispatch_async(queue, read_block_2);
dispatch_async(queue, read_block_3);
dispatch_async(queue, read_block_4);

dispatch_barrier_async(queue, update_block);

dispatch_async(queue, read_block_5);
dispatch_async(queue, read_block_6);
dispatch_async(queue, read_block_7);
dispatch_async(queue, read_block_8);
dispatch_async(queue, read_block_9);
这样就可以保证只有当更新操作结束后,才会进行其他数据库读操作,保证了数据的一致性。


dispatch_apply

dispatch_apply用于给一个block添加到dispatch queue若干次。 “for”循环

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_apply(10, queue, ^(size_t index) { NSLog(@"%zu",index);});

NSLog(@"done...");

dispatch_suspend/dispatch_resume

用于暂停和继续执行queue

dispatch semaphore

dispatch semaphore 适合处理比dispatch queue或者dispatch_barrier_async更小颗粒度的操作。

例如,

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{
      [array addObject:[NSNumber numberWithInt:i]];
    });
}

如果执行上段代码,因为NSMutableArray不是thread safe的,所以在global queue中对其进行添加对象,会导致程序crash掉。

使用dispatch semaphore我们可以实现多线程对NSMutableArray进行操作

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{

      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

      [array addObject:[NSNumber numberWithInt:i]];

      dispatch_semaphore_signal(semaphore);
    });
}

dispatch semaphore 是一个信号量的counter,当counter为0,当前线程停止运行,当大于0,自减1,继续执行。

dispatch_semaphore_create

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
初始化一个counter为1的semaphore.

dispatch_semaphore_wait

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
等待counter大于0才运行,第二个参数为等待时间。执行后counter减1.

dispatch_semaphore_signal

dispatch_semaphore_signal(semaphore);
给counter加1

所以在上面的代码中,就可以保证在wait和signal中的[array addObject:[NSNumber numberWithInt:i]]; 就只有一个thread进行操作,保证了线程安全。

dispatch_onece

保证了dispatch_once中的代码只会被执行一次,常用于单例。

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}

© 著作权归作者所有

共有 人打赏支持
董桉远
粉丝 35
博文 81
码字总数 20349
作品 0
朝阳
程序员
加载中

评论(2)

狗头666
狗头666
gcd?
悠哉悠哉e
悠哉悠哉e
学习了!2哈哈。再接再厉!
iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码

iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件(http://www.code4app.com/thread-14507-1-1.html) iOS高仿微信完整项目源码(http://www.code4app.com/thread-14695-1-1.html)......

sunnyaigd
06/12
0
0
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊
05/26
0
0
面试官自述:面向高级开发人员的iOS面试问题

当您准备进行技术性iOS面试时,了解您可能会询问哪些主题以及经验丰富的iOS开发人员期望什么是非常重要的。 这是许多硅谷公司用来衡量iOS候选人资历水平的一系列问题。 这些问题涉及iOS开发的...

菇哒微课
04/26
0
0
iOS multiple threads(2)------GCD

前面一二也说过,iOS中多线程编程工具主要有: NSThread NSOperation GCD 这三种方法都简单易用,各有千秋.同NSThread相比,GCD的运行效率更高,开发更简单。 但GCD确是诱惑力的,因为其本身是...

辉兔狼
2013/03/24
0
0
(转)直接拿来用!最火的iOS开源项目(二)

“每一次的改变总意味着新的开始。”这句话用在iOS上可谓是再合适不过的了。GitHub上的iOS开源项目数不胜数,iOS每一次的改变,总会引发iOS开源项目的演变,从iOS 1.x到如今的iOS 7,有的项目...

孙启超
2013/06/21
0
1
再看知名应用背后的第三方开源项目

知名应用程序的设计和技术一直都是开发者需要学习的,同样这些应用所使用的开源框架也是不可忽视的一部分。此前《iOS第三方开源库的吐槽和备忘》中作者ibireme列举了国内多款知名应用所使用的...

hejunbinlan
2015/08/18
0
0
[北京望京][15K-20K] 掘金招聘 iOS 开发

号外!号外!iOS 工程师又有人要啦! 望京 SOHO,望京 SOHO,iOS 工程师招聘了 你你你不来不来参加参加,你快投快投简历啊 不用犹豫了,我们等的就是你! ̋(ˊᵒ̴̶̷̤ ꇴ ᵒ̴̶̷̤ˋ)...

稀土君
07/11
0
0
iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码

iOS精选源码 一款优秀的 聆听夜空FM 源码(http://www.code4app.com/thread-14546-1-1.html) zhPopupController 简单快捷弹出自定义视图(http://www.code4app.com/thread-14861-1-1.html) WHS......

sunnyaigd
06/04
0
0
Unity与IOS交互,调用IOS系统相机和相册

前面两篇总结了一下unity与android的简单交互和调用安卓系统相机和相册,比较蛋疼的是,后来发现不同的测试机上会有不同的bug。。。下阶段要一个一个的解决一下 今天总结一下与IOS的交互。这...

qq_32587659
05/16
0
0
C++ Primer Plus(十七)——输入、输出和文件

cerr和clog对象与标准错误流对应,但cerr不被缓冲。 2. streambuf类为缓冲区提供了内存,并提供了用于填充缓冲区、访问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法。iosbase类表示流的一...

吃一堑消化不良
2017/11/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
3分钟前
0
0
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
14分钟前
0
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
20分钟前
0
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
35分钟前
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
41分钟前
0
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
49分钟前
0
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
50分钟前
0
0
安装tensorflow-XXX报错

报错: tensorflow-0.5.0-cp27-none-linux_x86_64.whl is not a supported wheel on this platform. 解决: wget https://bootstrap.pypa.io/get-pip.py sudo python2.7 get-pip.py sudo p......

Yao--靠自己
53分钟前
0
0
JVM学习手册(一):JVM模型

一直从事JAVA开发,天天和JVM打交道,仔细想想对JVM还真的不是特别了解,实在是不应该.周六看了许多资料,也算有点心得,记录一下。 JVM内存模型分为5个区域:方法区,堆,虚拟机栈,本地方法栈,程序计...

勤奋的蚂蚁
今天
0
0
转行零基础该如何学Python?这些一定要明白!

转行零基础学Python编程开发难度大吗?从哪学起?近期很多小伙伴问我,如果自己转行学习Python,完全0基础能否学会呢?Python的难度到底有多大?今天,小编就来为大家详细解读一下这个问题。...

猫咪编程
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部