多线程-GCD学习笔记
********************************* 基本概念 ***********************************
1. Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法,是苹果主推的多线程处理机制。在多核CPU的状态下,GCD的性能很高。
它自动利用更多的CPU内核,管理线程生命周期,程序员不需要编写任何线程管理代码,只需要给定要让GCD执行的任务。
2. GCD是纯C语言的,GCD中的函数大多数以dispatch开头。
3. GCD存在于 libdispatch.dylib 库中,但不需要手动导入,默认包含。
4. GCD的两个核心概念:任务 和 队列
将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行,遵行FIFO原则:先进先出,后进后出。
5. GCD一般和Block一起使用,在Block回调中处理程序操作。
****************************** GCD的三种调度队列 ******************************
首先需要明确4个术语的概念:
1. 异步(async):在另一条线路中执行,具备开启新线程的能力
2. 同步(sync):在当前线路执行,不具备开启新线程的能力
3. 并行(concurrent):自动开启多个线程让多个任务同时执行,并行功能只在异步条件下才有效
4. 串行(serial):一个任务执行完成才执行下一个
总而言之:同步和异步决定要不要开启新的线程,并行和串行决定任务执行的方式。
GCD的三种调度队列:
1. 运行在主线程的主队列Main queue,一般是执行和UI相关的任务比如更新UI的显示,通过dispatch_get_main_queue获取。
2. 并发队列global dispatch queue,一般是后台长时间执行的任务比如下载,默认提供,不需要创建,通过dispatch_get_global_queue获取。
dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags) // dislatch_queue_t 表示返回的是一个队列 /* 第一个参数dispatch_queue_priority_t priority表示优先级,后面会使用默认优先级 DISPATCH_QUEUE_PRIORITY_DEFAULT */ // 第二个参数unsigned long flags是以后才会使用的,所以先传0 // 用法 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); // 获得全局并发队列queue
3. 串行队列serial queues,获得串行有两种途径
1) 使用dispatch_queue_create函数创建串行队列
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
// 第一个参数是队列名称,第二个参数是队列属性,一般传NULL
// 用法
dispatch_queue_t queue = dispatch_queue_create("blahblahblah", NULL);
//非ARC需要手动释放队列
//dispatch_release(queue);
2) 使用主队列(一种特殊的串行队列,GCD自带的在主线程中执行的队列)
dispatch_get_main_queue() // 用法 dispatch_queue_t queue = dispatch_get_main_queue();
********************************* 代码示例 **********************************

1. 用异步函数向并发队列添加任务
// ViewController.m
#import <ViewController.h>
@interface ViewController()
@end
@implementation ViewController
-(void)viewDidLoad{
[super viewDidLoad];
//1. 获得全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,);
//2. 添加任务到队列中
dispatch_async(queue,^{
NSLog(@"下载图片1----%@",[NSThread currentThread]);
});
dispatch_async(queue,^{
NSLog(@"下载图片2----%@",[NSThread currentThread]);
});
dispatch_async(queue,^{
NSLog(@"下载图片3----%@",[NSThread currentThread]);
});
NSLog(@"主线程----%@",[NSThread mainThread]);
}
@end
// 异步,并发,开启了3个子线程
2. 用异步函数向串行队列添加任务
// ViewController.m
#import <ViewController.h>
@interface ViewController()
@end
@implementation ViewController
-(void)viewDidLoad{ [super viewDidLoad];
NSLog(@"主线程----%@",[NSThread mainThread]);
dispatch_queue_t queue = diapatch_queue_create("BlahBlahBlah",NULL);
dispatch_async(queue,^{
NSLog(@"下载图片1----%@",[NSThread currentThread])
});
dispatch_async(queue,^{
NSLog("下载图片2----%@",[NSThread currentThread]);
})
diapatch_async(queue,^{
NSLog("下载图片3----%@",[NSThread currentThread]);
})
// 释放队列
// dispatch_release(queue);
)
// 异步,串行,只开启一条子线程,子线程的任务串行执行
3. 用同步函数向并发队列添加任务
// ViewController.m
#import <ViewController.h>
@interface ViewController()
@end
@implementation ViewController
-(void)viewDidLoad{
[super viewDidLoad];
NSLog(@"主线程----%@",[NSThread mainThread]);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,);
dispatch_sync(queue,^{
NSLog("下载图片1----%@",[NSThread currentThread]);
})
dispatch_sync(queue,^{
NSLog("下载图片2----%@",[NSThread currentThread]);
})
dispatch_sync(queue,^{
NSLog("下载图片3----%@",[NSThread currentThread]);
})
)
// 同步,并发,并发队列失去并发功能,不具备开启新线程的能力,只有主线程
4. 用同步函数向串行队列添加任务
// ViewController.m
#import <ViewController.h>
@interface ViewController()
@end
@implementation ViewController
-(void)viewDidLoad{
[super viewDidLoad];
NSLog(@"主线程----%@",[NSThread mainThread]);
dispatch_queue_t queue = dispatch_queue_create("blahblahblah",NULL);
dispatch_sync(queue,^{
NSLog(@"下载图片1----%@",[NSThrea currentThread]);
})
dispatch_sync(queue,^{
NSLog(@"下载图片2----%@",[NSThrea currentThread]);
})
dispatch_sync(queue,^{
NSLog(@"下载图片3----%@",[NSThrea currentThread]);
})
)
@end
// 同步,串行,没有开启新线程的能力,只有主线程
总结:
同步函数
(1)并发队列:不会开线程
(2)串行队列:不会开线程
异步函数
(1)并发队列:能开启N条线程
(2)串行队列:开启1条线程
********************************线程死锁***********************************
不能使用同步函数向主线程添加任务:
dispatch_sync(diapatch_get_main_queue(),^{
NSLog("线程死锁");
})
在程序中写这样的语句不会有任何输出。
理解关键是:dispatch_sync 函数要到block里的内容执行完才能返回,主线程要等待函数返回。
dispatch_async 函数一被调用,马上返回,因此主线程得到返回就可以去做别的事。
原因在于:主线程调用同步函数dispatch_sync,添加任务到主队列(属于串行队列),主线程等待函数的返回,函数等待主线程结束才能执行block的内容,而同步函数必须等到执行完内部内容才能返回,因此造成线程死锁。
就像:A等待B买回来的材料才知道该干嘛,而B需要A提供自己要做什么的信息来决定买什么材料。
因此要向主队列中添加任务,用异步函数。
dispatch_async(dispatch_get_main_queue,^{
NSLog(@"不会造成线程死锁");
})
****************************持续更新中****************************
多线程-GCD学习笔记的更多相关文章
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- 多线程编程学习笔记——async和await(一)
接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...
- 多线程编程学习笔记——async和await(二)
接上文 多线程编程学习笔记——async和await(一) 三. 对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...
- 多线程编程学习笔记——async和await(三)
接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五. 处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...
- 多线程编程学习笔记——使用异步IO(一)
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
- 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端
接上文 多线程编程学习笔记——使用异步IO 二. 编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- 多线程编程学习笔记——使用异步IO
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
- Java多线程技术学习笔记(一)
目录: 概述 多线程的好处与弊端 JVM中的多线程解析 多线程的创建方式之一:继承Thread类 线程的状态 多线程创建的方式之二:实现Runnable接口 使用方式二创建多线程的好处 多线程示例 线 ...
随机推荐
- phpstorm 解决svn 无法提交的问题
phpstorm 无法用svn 提交 提示如下错误: 网上找的解决办法 : 由于安装的TortoiseSVN工具,本身是带有command-line功能的(没有安装)如图: 使用Intellij ID ...
- 基于前端javascript的搜索功能
发表于 2013/11/07 当在数据量不是很大,而且没有后端对应的功能接口的时候,一些简单的搜索功能基本上是前端去实现的,正好最近用到,写了一个,贴出来和大家分享: 功能描述: 按下键盘后及时搜索条 ...
- Android-用webservice连接sqlserver数据库
以前做的东西,只要用数据库的都是在项目里自己重新做一份数据.但是这种方法是很不可取的,首先,手机内存不会很大,把数据表建在项目里无疑又增大了程序.这样一来手机的运行速度可想而知.其次,数据大的时候还是 ...
- PureMVC(JS版)源码解析(八):Proxy类
前面,我们讲了与视图相关联的Mediator类,接下来我们讲讲与数据相关联的Proxy类. 关于Proxy类的作用,在Proxy类源码中,有这么一段注释: * In PureMVC, Proxy c ...
- 源码解析之–YYAsyncLayer异步绘制
来源:伯乐在线专栏作者 - Shelin 链接:http://ios.jobbole.com/86878/ 点击 → 了解如何加入专栏作者 前言 YYAsyncLayer是异步绘制与显示的工具.最初是 ...
- InnoDB还是MyISAM (摘录)
两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...
- Java Post 数据请求和接收
这两天在做http服务端请求操作,客户端post数据到服务端后,服务端通过request.getParameter()进行请求,无法读取到数据,搜索了一下发现是因为设置为text/plain模式才导致 ...
- Summary: How to calculate PI? Based on Monte Carlo method
refer to: http://www.stealthcopter.com/blog/2009/09/python-calculating-pi-using-random-numbers/ Duri ...
- 认识javascript作用域
JavaScript的作用域链 这是一个非常重要的知识点了,了解了JavaScript的作用域链的话,能帮助我们理解很多‘异常’问题. 下面我们来看一个小例子,前面我说过的声明提前的例子. var n ...
- sql sever怎样替换把表中数据。
怎样替换把表中“舞台桁架厂”替换为“舞台桁架厂家” 表数据结构为: id name key addre ...