GCD编程小记
2016-06-03 17:30
393 查看
Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统。这建立在任务并行执行的线程池模式的基础上的。Mac OS X 10.6+
,iOS 4+可用。它让OC的线程使用更方便,并且它还会自动根据任务在多核处理器上分配资源,优化程序。
工作原理:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
详细介绍:
1、GCD中的FIFO队列称为dispatch queue,它分为三种:Serial、Concurrent、Main dispatch queue。所有的调度队列都是先进先出队列,因此,队列中的任务的开始的顺序和添加到队列中的顺序相同。GCD自动的为我们提供了一些调度队列,我们也可以创建新的用于具体的目的。
下面列出几种可用的调度队列类型以及如何使用。
(1)serial queues(串行队列)又称私有调度队列(private),一般用再对特定资源的同步访问上。我们可以根据需要创建任意数量的串行队列,每一个串行队列之间是并发的。创建:
dispatch_queue_t serialQueue =
dispatch_queue_create("com.SerialQueue",
NULL);
不能随意的大量生产Serial Dispatch Queue。
(2)Concurrent并行队列,又称global dispatch queue。并行队列虽然可以并发的执行多个任务,但是任务开始执行的顺序和其加入队列的顺序相同。我们自己不能去创建并行调度队列。只有三个可用的global concurrent queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列,如下:
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
创建Concurrent
Dispatch Queue
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.ConcurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
Concurrent Dispatch Queue所使用的线程由系统的XNU内核高效管理,不会影响系统性能。
(3)main dispatch queue 是一个全局可用的串行队列,其在行用程序的主线程上执行任务。此队列的任务和应用程序的主循环(run loop)要执行的事件源交替执行。因为其运行在应用程序的主线程,main queue经常用来作为应用程序的一个同步点。
dispatch_async使用,当我们的App页面处理读取网络数据、数据库读写等耗时操作时会导致我们的UI呈现卡顿,这个时候我们就需要另外开一个线程处理这些操作,处理完成之后再通知主线程更新界面,并且UI的更新只能在主线程中。
用GCD实现这个流程的操作比NSThread NSOperation的方法都要简单。代码框架结构如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
// Do time-consuming task in background thread
// Return back to main thread to update UI
// UI更新要在主线程中,否则会有崩溃
dispatch_sync(dispatch_get_main_queue(), ^{
//做和UI相关操作
});
});
除了调度队列,GCD还提供了一些有用的技术如dispath group ,dispatch semaphore, dispatch sources,等来帮助我们管理代码
2、dispatch_group_async使用
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。下面是一段例子代码:
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(@"group1");
});
dispatch_group_async(group, queue, ^{
//第二件事
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
//第三件事
NSLog(@"group3");
});
dispatch_group_notify(group,
dispatch_get_main_queue(), ^{
//更新UI
NSLog(@"updateUi");
});
3、dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
//dispatch_queue_create
用于创建用户线程队列。可以创建Serial/Concurrent Dispatch Queue
两种队列,即串行与并行队列。
dispatch_queue_t queue =
dispatch_queue_create("aaa.bbb.ccc",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread
sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
执行某个代码片段N次。
dispatch_apply(5, globalQ, ^(size_t index) {
// 执行5次
});
备注:
对于最低sdk版本>=ios6.0来说,GCD对象已经纳入了ARC的管理范围,我们就不需要再手工调用 dispatch_release了,否则的话,在sdk<6.0的时候,即使我们开启了ARC,这个宏OS_OBJECT_USE_OBJC
也是没有的,也就是说这个时候,GCD对象还必须得自己管理
如果你部署的最低目标低于 iOS 6.0 or Mac OS X 10.8
你应该自己管理GCD对象,使用(dispatch_retain,dispatch_release),ARC并不会去管理它们
如果你部署的最低目标是 iOS 6.0 or Mac OS X 10.8 或者更高的
ARC已经能够管理GCD对象了,这时候,GCD对象就如同普通的OC对象一样,不应该使用dispatch_retain ordispatch_release
对于串行队列,每创建一个串行队列,系统就会对应创建一个线程,同时这些线程都是并行执行的,只是在串行队列中的任务是串行执行的。大量的创建串行队列会导致大量消耗内存,这是不可取的做法。串行队列的优势在于他是一个线程,所以在操作一个全局数据时候是线程安全的。当想并行执行而不发生数据竞争时候可以用并行队列操作
,iOS 4+可用。它让OC的线程使用更方便,并且它还会自动根据任务在多核处理器上分配资源,优化程序。
工作原理:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
详细介绍:
1、GCD中的FIFO队列称为dispatch queue,它分为三种:Serial、Concurrent、Main dispatch queue。所有的调度队列都是先进先出队列,因此,队列中的任务的开始的顺序和添加到队列中的顺序相同。GCD自动的为我们提供了一些调度队列,我们也可以创建新的用于具体的目的。
下面列出几种可用的调度队列类型以及如何使用。
(1)serial queues(串行队列)又称私有调度队列(private),一般用再对特定资源的同步访问上。我们可以根据需要创建任意数量的串行队列,每一个串行队列之间是并发的。创建:
dispatch_queue_t serialQueue =
dispatch_queue_create("com.SerialQueue",
NULL);
不能随意的大量生产Serial Dispatch Queue。
(2)Concurrent并行队列,又称global dispatch queue。并行队列虽然可以并发的执行多个任务,但是任务开始执行的顺序和其加入队列的顺序相同。我们自己不能去创建并行调度队列。只有三个可用的global concurrent queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列,如下:
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
创建Concurrent
Dispatch Queue
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.ConcurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
Concurrent Dispatch Queue所使用的线程由系统的XNU内核高效管理,不会影响系统性能。
(3)main dispatch queue 是一个全局可用的串行队列,其在行用程序的主线程上执行任务。此队列的任务和应用程序的主循环(run loop)要执行的事件源交替执行。因为其运行在应用程序的主线程,main queue经常用来作为应用程序的一个同步点。
dispatch_async使用,当我们的App页面处理读取网络数据、数据库读写等耗时操作时会导致我们的UI呈现卡顿,这个时候我们就需要另外开一个线程处理这些操作,处理完成之后再通知主线程更新界面,并且UI的更新只能在主线程中。
用GCD实现这个流程的操作比NSThread NSOperation的方法都要简单。代码框架结构如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
// Do time-consuming task in background thread
// Return back to main thread to update UI
// UI更新要在主线程中,否则会有崩溃
dispatch_sync(dispatch_get_main_queue(), ^{
//做和UI相关操作
});
});
除了调度队列,GCD还提供了一些有用的技术如dispath group ,dispatch semaphore, dispatch sources,等来帮助我们管理代码
2、dispatch_group_async使用
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。下面是一段例子代码:
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(@"group1");
});
dispatch_group_async(group, queue, ^{
//第二件事
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
//第三件事
NSLog(@"group3");
});
dispatch_group_notify(group,
dispatch_get_main_queue(), ^{
//更新UI
NSLog(@"updateUi");
});
3、dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
//dispatch_queue_create
用于创建用户线程队列。可以创建Serial/Concurrent Dispatch Queue
两种队列,即串行与并行队列。
dispatch_queue_t queue =
dispatch_queue_create("aaa.bbb.ccc",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread
sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread
sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
4、dispatch_apply
执行某个代码片段N次。dispatch_apply(5, globalQ, ^(size_t index) {
// 执行5次
});
备注:
对于最低sdk版本>=ios6.0来说,GCD对象已经纳入了ARC的管理范围,我们就不需要再手工调用 dispatch_release了,否则的话,在sdk<6.0的时候,即使我们开启了ARC,这个宏OS_OBJECT_USE_OBJC
也是没有的,也就是说这个时候,GCD对象还必须得自己管理
你应该自己管理GCD对象,使用(dispatch_retain,dispatch_release),ARC并不会去管理它们
如果你部署的最低目标是 iOS 6.0 or Mac OS X 10.8 或者更高的
ARC已经能够管理GCD对象了,这时候,GCD对象就如同普通的OC对象一样,不应该使用dispatch_retain ordispatch_release
对于串行队列,每创建一个串行队列,系统就会对应创建一个线程,同时这些线程都是并行执行的,只是在串行队列中的任务是串行执行的。大量的创建串行队列会导致大量消耗内存,这是不可取的做法。串行队列的优势在于他是一个线程,所以在操作一个全局数据时候是线程安全的。当想并行执行而不发生数据竞争时候可以用并行队列操作
相关文章推荐
- C# 目录(文件夹)复制实现
- C#在winform中调用系统控制台输出
- 第三方登录插件.NET版XY.OAuth-CSharp
- java三方---->html解析jsoup的使用
- 实战记录:从EclipseLink迁移到Hibernate上(1)替换
- Excel数据提取C++代码(仅供参考)
- Java中的IO笔记Mars
- Q1010 Tempter of the Bone C++ (深度优先搜索)
- 【Leetcode】287. Find the Duplicate Number My Submissions QuestionEditorial Solution python实现
- spring,mybatis,druid,多数据源配置
- C++Primer:函数(参数传递:引用形参)
- PHP笔记1
- A java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Ecl
- 反射获取对象中属性的信息,包括属性的特性
- Caused by: java.lang.IllegalArgumentException: prefix wsdp is not bound to a namespace
- live555源代码分析
- Python subprocess模块
- Django里自定义用户登陆及登陆后跳转到登陆前页面的实现
- MVC过滤器详解
- C#—实验10.1和10.2