[New learn]GCD的基本使用
https://github.com/xufeng79x/GCDDemo
1.简介
介绍GCD的使用,介绍多种队列与同步异步多种情况下的组合运行情况。
2.基本使用步骤
如果使用GCD则一般也就两个步骤
1.创建/获取执行队列
2.同步或者异步在队列中执行任务 ,通常任务为一个block
3.队列与执行类型(同步或者异步)的组合运行情况
GCD的队列分为串行队列和并发队列,这两种队里都可以自行创建。
除了能够自行创建队列外,系统中已经存在了主队列和全局队列,这两个队列我们可以直接获取使用。
GCD的任务执行方式有分为同步和异步两种。所以根据队列类型和执行方式我们可以排列组合进行选择,下面我们将对这种组合
加以测试来探索他们的不同表现。
| 执行方式/队列类型 | 自建串行队列 | 自建并发队列 | 主队列 | 全局队列 |
|
同步 |
||||
|
异步 |
3.1 自建串行队列+同步执行
/**
* 串行+同步方式执行任务
* 任务顺序:先进先出
* 线程启动方式:不开启新线程,全部在当前线程中执行
*/
-(void) test1
{
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("xf", DISPATCH_QUEUE_SERIAL);
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 同步方式启动任务
dispatch_sync(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
执行结果:
-- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] 完成!
总结:
/** * 串行+同步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:不开启新线程,全部在当前线程中执行 */
3.2 自建串行队列+异步执行
/**
* 串行+异步方式执行任务
* 任务顺序:先进先出
* 线程启动方式:开启新线程且只开启一个新线程,全部在新线程中执行
*/
-(void) test2
{
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("xf", DISPATCH_QUEUE_SERIAL);
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 同步方式启动任务
dispatch_async(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] 完成! -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)}
总结:
/** * 串行+异步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:开启新线程且只开启一个新线程,全部在新线程中执行 */
3.3 自建并发队列+同步执行
/**
* 并发队列+同步方式执行任务
* 任务顺序:先进先出
* 线程启动方式:不开启新线程,全部在当前线程中执行
*/
-(void) test3
{
// 创建队列
dispatch_queue_t queue = dispatch_queue_create("xf", DISPATCH_QUEUE_CONCURRENT);
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_sync(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] 完成!
总结:
/** * 并发队列+同步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:不开启新线程,全部在当前线程中执行 */
3.4 自建并发队列+异步执行
/**
* 并发队列+异步方式执行任务
* 任务顺序:无序
* 线程启动方式:开启多个线程,在多个线程中可以同时执行多个任务
*/
-(void) test4
{
// 创建队列
dispatch_queue_t queue = dispatch_queue_create("xf", DISPATCH_QUEUE_CONCURRENT);
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_async(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] 完成! -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)}
总结:
/** * 并发队列+异步方式执行任务 * 任务顺序:无序 * 线程启动方式:开启多个线程,在多个线程中可以同时执行多个任务 */
接下来我们来测试一下两个特殊的队列:主队列和全局队列
主队列:负责在主线程上调度任务,顺序执行其中任务。其中的任务不会运行与子线程,换句话说无论是同步还是异步都不会开子线程。
3.5 主队列+同步执行
/**
* 主队列+同步方式执行任务
* 任务顺序:卡死
* 线程启动方式:卡死
*/
-(void) test5
{
// 创建队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_sync(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
无
总结:
/** * 主队列+同步方式执行任务 * 任务顺序:卡死 * 线程启动方式:卡死 */
3.6 主队列+异步执行
/** * 主队列+异步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:不开启新线程,只在主线程中执行(需要等到主线程中当前任务完成后再执行后续任务,可观察到先打印“完成“) */
-(void) test6
{
// 创建队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_async(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] 完成! -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main}
总结:
/** * 主队列+异步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:不开启新线程,只在主线程中执行(需要等到主线程中当前任务完成后再执行后续任务,可观察到先打印“完成”) */
3.7 全局队列+同步执行
/**
* 全局队列+同步方式执行任务
* 任务顺序:先进先出
* 线程启动方式:不开启新线程,只在主线程中执行
*/
-(void) test7
{
// 创建队列
dispatch_queue_t queue = dispatch_get_global_queue(, );
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_sync(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] execute task : , name = main} -- :::] 完成!
总结:
/** * 全局队列+同步方式执行任务 * 任务顺序:先进先出 * 线程启动方式:不开启新线程,只在主线程中执行 */
3.8 全局队列+异步执行
/**
* 全局队列+异步方式执行任务
* 任务顺序:无序
* 线程启动方式:开启多个新线程,不同任务可在不同线程中并发执行
*/
-(void) test8
{
// 创建队列
dispatch_queue_t queue = dispatch_get_global_queue(, );
// 循环调用,确定任务的放置于启动顺序
; i < ; i++)
{
// 启动任务
dispatch_async(queue,^{
NSLog(@"execute task : %d in thread : %@", i, [NSThread currentThread]);
});
}
NSLog(@"%@", @"完成!");
}
结果:
-- :::] 完成! -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)} -- :::] execute task : , name = (null)}
总结:
/** * 全局队列+异步方式执行任务 * 任务顺序:无序 * 线程启动方式:开启多个新线程,不同任务可在不同线程中并发执行 */
4.至此对于GCD的一般用法总结如下:
| 执行方式/队列类型 | 自建串行队列 | 自建并发队列 | 主队列 | 全局队列 |
|
同步 |
1.不开启新线程 2.先进先出顺序执行 |
1.不开启新线程 2.先进先出顺序执行 |
卡死 |
1.不开启新线程 2.先进先出顺序执行 |
|
异步 |
1.开启新线程,且只开启一个新线程。 2.先进先出顺序执行,且只在新线程中执行 |
1.开启多个线程,任务可在多个线程中并发执行 2.无序执行 |
1.不开启新线程,只在主线程中执行 2.先进先出顺序执行 |
1.开启多个线程,任务可在多个线程中并发执行 2.无序执行 |
有此我们可以看出:
1.同步执行方式都不会新建线程。
2.当队列为串行队列,则在异步执行方式下也只会开启一个线程,因为队列性质决定,开启多个线程也是徒劳无功。
3.主队列只能在主线程下执行。
3.全局队列的表现和自建并发队列一致,所以平时可以直接使用全局队列。
5.更进一步
我们看到GCD中存在卡死的现象,那么什么时候回出现这种情况呢?下一篇博文[New learn]GCD的卡死现象分析研究继续分析研究。
[New learn]GCD的基本使用的更多相关文章
- [New learn]GCD的卡死现象分析研究
https://github.com/xufeng79x/GCDDemo 1.简介 前接[New learn]GCD的基本使用,我们分析了GCD的一般使用方法,其中比较特殊的是在分析到主队列的时候发生 ...
- [New learn]GCD其他方法的使用
https://github.com/xufeng79x/GCDDemo 1.简介 在前面的两篇博文中我介绍了GCD的一般使用方法和死锁的分析调查.本博文中继续讲解GCD的其他比较常用的几个使用方法. ...
- bzoj 2818: Gcd GCD(a,b) = 素数
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1566 Solved: 691[Submit][Status] Descript ...
- Multithreading annd Grand Central Dispatch on ios for Beginners Tutorial-多线程和GCD的入门教程
原文链接:Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial Have you ever written a ...
- SPOJ PGCD 4491. Primes in GCD Table && BZOJ 2820 YY的GCD (莫比乌斯反演)
4491. Primes in GCD Table Problem code: PGCD Johnny has created a table which encodes the results of ...
- [New learn] 设计模式思考
本文是对上文[New learn] 设计模式的思考总结 1.大框架 无论应用使用多少种设计模式和技巧,此模式都是应用的大框架.下图为本项目的基本架构图: 1.上图中大框架为经典的MVC模式. 2.Co ...
- SPOJ4491. Primes in GCD Table(gcd(a,b)=d素数,(1<=a<=n,1<=b<=m))加强版
SPOJ4491. Primes in GCD Table Problem code: PGCD Johnny has created a table which encodes the result ...
- Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用
OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...
- iOS 多线程之GCD的使用
在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...
随机推荐
- CentOS 挂载(U盘NTFS格式,新硬盘,增加交换分区,扩展根分区等)
1.挂载fat或者fat32分区的U盘 如果是用VM安装的linux,在vm里挂载U盘有两个前提: 第一,主机里的service要启动: 第二,U盘是连接到虚拟机,而不是主机,需要确认这点: 2.使用 ...
- 后缀自动机SAM学习笔记
前言(2019.1.6) 已经是二周目了呢... 之前还是有一些东西没有理解到位 重新写一下吧 后缀自动机的一些基本概念 参考资料和例子 from hihocoder DZYO神仙翻译的神仙论文 简而 ...
- [NOI.AC省选模拟赛3.31] 附耳而至 [平面图+最小割]
题面 传送门 思路 其实就是很明显的平面图模型. 不咕咕咕的平面图学习笔记 用最左转线求出对偶图的点,以及原图中每个边两侧的点是谁 建立网络流图: 源点连接至每一个对偶图点,权值为这个区域的光明能量 ...
- HDU.1285 确定比赛名次 (拓扑排序 TopSort)
HDU.1285 确定比赛名次 (拓扑排序 TopSort) 题意分析 裸的拓扑排序 详解请移步 算法学习 拓扑排序(TopSort) 只不过这道的额外要求是,输出字典序最小的那组解.那么解决方案就是 ...
- HDOJ(HDU).4508 湫湫系列故事――减肥记I (DP 完全背包)
HDOJ(HDU).4508 湫湫系列故事――减肥记I (DP 完全背包) 题意分析 裸完全背包 代码总览 #include <iostream> #include <cstdio& ...
- bzoj Usaco补完计划(优先级 Gold>Silver>资格赛)
听说KPM初二暑假就补完了啊%%% 先刷Gold再刷Silver(因为目测没那么多时间刷Silver,方便以后TJ2333(雾 按AC数降序刷 ---------------------------- ...
- [zhuan]arm中的汇编指令
http://blog.csdn.net/qqliyunpeng/article/details/45116615 一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text& ...
- mysql定时器,定时查询数据库,把查询结果插入到一张表中
1.有两张表order_repayment_detail,msg_sim ,需要把前者中的按时间过滤出来的信息插入到短信发送表中,可以每晚12点钟查询执行一次查询. 创建存储过程,这里的存储过程主要提 ...
- 使用 Rational AppScan 保证 Web 应用的安全性,第 2 部分: 使用 Rational AppScan 应对 Web 应用攻击
1 当前 Web 安全现状 互联网的发展历史也可以说是攻击与防护不断交织发展的过程.目前,全球因特网用户已达 13.5 亿,用户利用网络进行购物.银行转账支付和各种软件下载,企业用户更是依赖于互联网构 ...
- HEOI 2012 旅行问题
2746: [HEOI2012]旅行问题 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1009 Solved: 318[Submit][Statu ...