本文主要对GCD的概念、API以及实现进行梳理.
一.CCD的概念.
1.GCD,全称是Grand Central Dispatch,它是C语言的API.
GCD的核心 : 将block(任务)添加到queue(队列)中.
根据官方文档ConcurrencyProgramingGuide中的描述:
One of the technologies for starting tasks asynchronously is Grand Central Dispatch (GCD). This technology takes the thread management code you would normally write in your own applications and moves that code down to the system level. All you have to do is define the tasks you want to execute and add them to an appropriate dispatch queue. GCD takes care of creating the needed threads and of scheduling your tasks to run on those threads. Because the thread management is now part of the system, GCD provides a holistic approach to task management and execution, providing better efficiency than traditional threads.
翻译如下:
Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并执行任务,这样就比以前的线程更有效率.
2.GCD使用步骤
- 创建任务 : 确定具体要做的事.
GCD中的任务是使用block封装的. - 将任务添加到队列中
GCD会自动将队列中的任务取出,放到对应的线程中执行.
任务的取出遵循队列的FIFO原则 : 先进先出,后进后出.
3.日常使用
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
/**
* 长时间处理
*
* 例如 AR 用画像识别
* 例如数据库访问
*/
dispatch_async(queue, ^{
/**
* 长时间处理结束,主线程使用该处理结果
*/
dispatch_async(dispatch_get_main_queue(), ^{
/**
* 只有在主线程可以执行的处理
*
* 例如用户界面更新
*/
});
});
在GCD之前,Cocoa框架提供了NSObject类的performSelectorInBackground:withObject:
实例方法和
实例方法等简单的多线程编程技术.
performSelectorOnMainThread:withObject:waitUntilDone:
以下方法等价于GCD的实现:
/**
* NSObject performSelectorInBackground: withObject:方法中
* 执行后台线程
*/
- (void)launchThreadByNSObject_performSelectorInBackground_withObject
{
[self performSelectorInBackground:@selector(doWork) withObject:nil];
}
- (void)doWork
{
/**
* 因为书本是基于MRC环境所写,所以包含自动释放池,若在ARC环境下,以下语句会报错.
*/
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/**
* 长时间处理
*
* 例如 AR 用画像识别
* 例如数据库访问
*/
/**
* 长时间处理结束,主线程使用该处理结果
*/
[self performSelectorOnMainThread:@selector(doneWork) withObject:nil waitUntilDone:NO];
[pool drain];
}
- (void)doneWork
{
/**
* 只有在主线程可以执行的处理
*
* 例如用户界面更新
*/
}
4.多线程执行原理总结
单核CPU同一时间,CPU只能处理1个线程,只有1个线程在执行任务.
多线程的同时执行 : 其实是CPU在多条线程之间快速切换(调度任务).
如果CPU调度线程的速度足够快,就造成了多线程同时执行的假象.
在多核CPU的情况下,就真正并行执行多个线程.
因为长时间的处理(耗时操作)
,会妨碍主线程的运行循环的执行,所以需要进行多线程编程,如:异步
创建子线程
去处理耗时操作
,耗时操作结束后,再回到主线程刷新UI
.这种方式不会妨碍主线程的运行循环的执行,并能提高程序响应性能.
如图:
二.CCD的API.
Dispatch Queue
开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中.
源代码表示:
dispatch_async(queue, ^{
/**
* 想执行的任务
*/
});
Dispatch Queue是执行处理的等待队列.Dispatch Queue按照追加的顺序(先进先出FIFO,First-In-First-Out)执行处理.
如图:
Dispatch Queue分为4种队列,分别是Serial Queue
(串行队列)、Concurrent Queue
(并发队列)、Main Dispatch Queue
(主调度队列)、Global Dispatch Queue
(全局并发队列).
根据官方文档Dispatch Queues中的描述:
1.Serial Queue
Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue.
If you create four serial queues, each queue executes only one task at a time but up to four tasks could still execute concurrently, one from each queue.
翻译如下:
串行队列(也称为私有调度队列)按顺序将其中一个任务添加到队列中,并且一次只执行一个任务.
如果创建四个串行队列,每个队列一次只执行一个任务,但最多四个任务可以并发执行,每个队列中有一个任务.
如图:
代码:
dispatch_queue_t queue = dispatch_queue_create("mySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"一个丁老头,欠我两个蛋");
});
dispatch_async(queue, ^{
NSLog(@"他说三天还,四天还没还");
});
dispatch_async(queue, ^{
NSLog(@"仔细想一想,就是大傻蛋");
});
dispatch_async(queue, ^{
NSLog(@"买了三根葱,花了3毛3");
});
dispatch_async(queue, ^{
NSLog(@"买个大西瓜,用了6毛6");
});
dispatch_async