关于多线程之GCD的一些学习要点
GCD是当前多线程使用最方便的,也是使用比较多的。
学习GCD主要集中在一下几点:
一、队列,同步,异步
1.主队列:dispatch_get_main_queue();
2.串行队列:dispatch_queue_create("queue", 0);
3.并行队列:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
4.同步,异步就不需要再多说什么。
对上面关键词的一些解释:
主队列:主队列只能使用异步来执行队列中的任务,使用同步的话会造成死循环。同时执行任务的时候是在主线程中执行的。
串行队列:(1)、添加到串行队列中的任务是一个接着一个执行的,也就是当上一个任务执行完之后才开始下一个任务;
但是可以创建多个串行队列,每个串行队列之间是相互独立的,可以并发执行。
(2)、如果用同步执行的话就是在当前线程上执行;
(3)、如果用异步执行的话就是新开辟一个线程执行。
并行队列:(1)、添加到并行队列中的任务可以并发启动,启动顺序仍然是一个接着一个,但是后者可以不等前者执行完就可以开始执行。
并行队列也可以创建多个,各个之间也是相互独立,并发执行的。
(2)、如果用同步执行的话就是在当前线程上执行;
(3)、如果用异步执行的话就是新开辟一个线程执行。
二、经常用到的地方
1.任务执行完毕之后再进行一些操作
2.只执行一次
3.延时操作
对上面用处的一些解释:
(1)、任务执行完毕之后再进行一些操作,如果是一些简单的操作可以直接使用串行队列实现。但是一些比较费时的操作就需要用到队列组了。
//1.创建一个队列组
dispatch_group_t group = dispatch_group_create();
//2.开启一个任务1
dispatch_group_async(group, global_quque, ^{
});
//3.开启一个任务2
dispatch_group_async(group, global_quque, ^{
});
//4.等group中的所有任务都执行完毕, 再回到主线程执行其他操作
dispatch_group_notify(group,main_queue, ^{
});
(2)、只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只执行1次的代码(这里面默认是线程安全的)
});
(3)、延时操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//延迟执行的方法
});
(4)、暂停和恢复队列中的任务
dispatch_suspend和dispatch_resume
我们知道NSOperationQueue有暂停(suspend)和恢复(resume)。其实GCD中的队列也有类似的功能。用法也非常简单:
dispatch_suspend(queue) //暂停某个队列
dispatch_resume(queue) //恢复某个队列
这些函数不会影响到队列中已经执行的任务,队列暂停后,已经添加到队列中但还没有执行的任务不会执行,直到队列被恢复。
(5)、承上启下
dispatch_async(queue, block1_for_reading)
dispatch_async(queue, block2_for_reading)
dispatch_barrier_async(queue, block_for_writing)
dispatch_async(queue, block3_for_reading)
dispatch_async(queue, block4_for_reading)
dispatch_barrier_async 会把并行队列的运行周期分为这三个过程:
- 首先等目前追加到并行队列中所有任务都执行完成
- 开始执行 dispatch_barrier_async 中的任务,这时候即使向并行队列提交任务,也不会执行
- dispatch_barrier_async 中的任务执行完成后,并行队列恢复正常。
总的来说,dispatch_barrier_async 起到了“承上启下”的作用。它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。正如barrier的含义一样,它起到了一个栅栏、或是分水岭的作用。
这样一来,使用并行队列和 dispatc_barrier_async 方法,就可以高效的进行数据和文件读写了。
(6)、信号量
dispatch_semaphore
首先介绍一下信号量(semaphore)的概念。信号量是持有计数的信号,不过这么解释等于没解释。我们举个生活中的例子来看看。
假设有一个房子,它对应进程的概念,房子里的人就对应着线程。一个进程可以包括多个线程。这个房子(进程)有很多资源,比如花园、客厅等,是所有人(线程)共享的。
但是有些地方,比如卧室,最多只有两个人能进去睡觉。怎么办呢,在卧室门口挂上两把钥匙。进去的人(线程)拿着钥匙进去,没有钥匙就不能进去,出来的时候把钥匙放回门口。
这时候,门口的钥匙数量就称为信号量(Semaphore)。很明显,信号量为0时需要等待,信号量不为零时,减去1而且不等待。
在GCD中,创建信号量的语法如下:
var semaphore = dispatch_semaphore_create(2)
这句代码通过 dispatch_semaphore_create 方法创建一个信号量并设置初始值为 2。然后就可以调用 dispatch_semaphore_wait 方法了。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_semaphore_wait 方法表示一直等待直到信号量的值大于等于 1,当这个方法执行后,会把第一个信号量参数的值减 1。
第二个参数是一个 dispatch_time_t 类型的时间,它表示这个方法最大的等待时间。这在第一章中已经讲过,比如 DISPATCH_TIME_FOREVER 表示永久等待。
返回值也和 dispatch_group_wait 方法一样,返回 0 表示在规定的等待时间内第一个参数信号量的值已经大于等于 1,否则表示已超过规定等待时间,但信号量的值还是 0。
dispatch_semaphore_wait 方法返回 0,因为此时的信号量的值大于等于一,任务获得了可以执行的权限。这时候我们就可以安全的执行需要进行排他控制的任务了。
任务结束时还需要调用 dispatch_semaphore_signal() 方法,将信号量的值加 1。这类似于之前所说的,从卧室出来要把锁放回门上,否则后来的人就无法进入了。
我们来看一个完整的例子:
var semaphore = dispatch_semaphore_create(1)
let queue = dispatch_queue_create("com.gcd.kt", DISPATCH_QUEUE_CONCURRENT)
var array: [Int] = []
for i in 1...100000 {
dispatch_async(queue, { () -> Void in
/*
某个线程执行到这里,如果信号量值为1,那么wait方法返回1,开始执行接下来的操作。
与此同时,因为信号量变为0,其它执行到这里的线程都必须等待
*/
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
/*
执行了wait方法后,信号量的值变成了0。可以进行接下来的操作。
这时候其它线程都得等待wait方法返回。
可以对array修改的线程在任意时刻都只有一个,可以安全的修改array
*/
array.append(i)
/*
排他操作执行结束,记得要调用signal方法,把信号量的值加1。
这样,如果有别的线程在等待wait函数返回,就由最先等待的线程执行。
*/
dispatch_semaphore_signal(semaphore)
})
}
总结:
1、常用的延时操作:
(1) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//延迟执行的方法
});
(2) [self performSelector:@selector(test) withObject:nil afterDelay:1.0];
2、回到主线程的操作:
(1) dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执⾏UI刷新操作 });
(2) [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
关于多线程之GCD的一些学习要点的更多相关文章
- iOS多线程之GCD小记
iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...
- iOS多线程之GCD学习笔记
什么是GCD 1.全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 2.纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 G ...
- iOS 多线程之GCD的使用
在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...
- iOS-多线程之GCD(原创)
前言 GCD 全称 Grand Central DisPath NSOperation便是基于GCD的封装 基础知识 1.GCD的优势 (1)为多核的并行运算提出了解决方案 (2)GCD会自动利用更多 ...
- 多线程之GCD
什么是GCD Grand Central Dispatch 是Apple开发的一种多核编程技术.主要用于优化应用程序以支持多核处理器以及其他多对称处理系统TA会自动管理线程的生命周期(创建线程.调度任 ...
- iOS多线程之GCD详解
GCD(Grand Central Dispatch)是基于C语言开发的一套多线程开发机制.也是目前苹果官方推荐的多线程开发方法.iOS三种多线程开发中GCD是抽象层次最高的.当然用起来也是最简单的. ...
- IOS中的多线程之GCD
在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下CDD的使用. GCD(Grand Central D ...
- IOS 多线程之GCD
参考:http://www.cnblogs.com/wendingding/p/3806821.html <<Objective-C基础教程>> 第二版 一 简介 GCD 全称 ...
- (五十五)iOS多线程之GCD
GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法. 进程和线程的概念: 正在进行中的程序被称为进程,负责程序运行的内存分配,每一个 ...
随机推荐
- rabbitmq3.7.5 centos7 集群部署笔记
1. 准备3台 centos服务器 192.168.233.128 192.168.233.130 192.168.233.131 防火墙放开 集群端口, 这里一并把所有rabbitmq ...
- Jmeter入门(压力测试)
Jmeter介绍 Jmeter是一款使用Java开发的,开源免费的,测试工具, 主要用来做功能测试和性能测试(压力测试/负载测试). 而且用Jmeter 来测试 Restful API, 非常好用. ...
- HTML学习之给div高度设置百分比不生效的问题
这几天在学习HTML的知识,今天想做一个极为简单的页面,就是分为头部,内容和底部,本来用三个div即可,可是给div高度设置百分比时发现不生效,具体页面如下,非常简单. 下面是html部分: < ...
- 部署Asp.net core & Nginx,通过nginx转发
部署Asp.net core & Nginx,通过nginx转发 CentOS 7 x64 1.vs2017 建立Asp.net core项目,并发布到目录 2.通过FTP工具,将程序copy ...
- Python学习(二十八)—— Django模板系统
转载自http://www.cnblogs.com/liwenzhou/p/7931828.html Django模板系统 官方文档 一.常用语法 只需要记两种特殊符号: {{ }}和 {% %} ...
- Python学习(八) —— 内置函数和匿名函数
一.递归函数 定义:在一个函数里调用这个函数本身 递归的最大深度:997 def func(n): print(n) n += 1 func(n) func(1) 测试递归最大深度 import sy ...
- UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ23.html 题目传送门 - UOJ#23 题意 给定一个有 n 个节点的仙人掌(可能有重边). 对于所有 ...
- Codeforces Gym100187C Very Spacious Office 贪心 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100187C.html 题目传送门 - CF-Gym100187C 题意 给定 $n$ 个房间以及 ...
- LoadRunner脚本参数化之设置条件与运行结果说明
性能测试中为什么需要进行参数化? 1.功能方面:首先要保证脚本的功能完善.可用性.(一般来说,参数化主要针对业务中的具备唯一性的数据.) 2.性能方面:一般来说,如果服务器存在缓存机制,在测试过程中, ...
- busybox linux-2.6.2 编译安装中碰到的若干问题
Q1 /busybox-1.18.4/scripts/gcc-version.sh: line 11: arm-linux-gcc: command not found 1.问题:/home/ub ...