Grand Central Dispatch,或者简称 GCD,是一个与 Block Object 产生工作的低级的 C API。GCD 真正的用途是将任务分配到多个核心又不让程序员担心哪个内核执行哪个任务。 在 Max OS X 上,多内核设备,包括笔记本,用户已经使用了相当长的时间。通过多核设备 比如 iPad2 的介绍,程序员能为 iOS 写出神奇的多核多线程 APP。
一、线程管理常用方法
1.performSelector(InBackground or MainThread)
这个方法比较方便,但是问题在于参数传递只能支持一个对象(传多个参数,我是将其打包在一个NSDictionary里面)
2.NSOperationQueue
这个方法稍微复杂,提供了每个任务的封装(NSOperation)。可以继承NSOperation之后,在main函数中写一些同步执行的代码,然后放到一个Queue之中,Queue自动管理Operation的执行和调度(在UI线程以外)。对于异步执行的代码,需要重载NSOperation的好几个函数才能正常工作(告诉Queue关于这个任务的进度以及执行情况)。
3.NSThread
轻量级的线程管理机制
4.GCD
在UI线程和其它线程之间切换很方便,可以和NSOperationQueue搭配使用。本文着重介绍这个方法。
5,pthread
二、GCD使用示例
GCD 的核心是分派队列。不论在 iOS 还是 Max OS X 分派队列,正如我们快看到的是 由位于主操作系统的 GCD 来管理的线程池。你不会直接与线程有工作关系。你只在分派队 列上工作,将任务分派到这个队列上并要求队列来调用你的任务。GCD 为运行任务提供了 几个选择:同步执行、异步执行和延迟执行等。
1、网络下载
以点击一个按钮,然后显示loading,同时在后台下载一张图片,最后将下载的图片放到UIImageView中显示为例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//显示loading
self.indicator.hidden = NO;
[self.indicator startAnimating];
//进入异步线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//异步下载图片
NSURL * url = [NSURL URLWithString:@ "http://anImageUrl" ];
NSData * data = [NSData dataWithContentsOfURL:url];
//网络请求之后进入主线程
dispatch_async(dispatch_get_main_queue(), ^{
//关闭loading
[self.indicator stopAnimating];
self.indicator.hidden = YES;
if (data) { //显示图片
self.imageView.image = [UIImage imageWithData:data];
}
});
});
|
2、延迟执行
1
2
3
4
5
6
|
// 延迟2秒执行:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^( void ){
// code to be executed on the main queue after delay
});
|
3、自定义GCD
可以使用dispatch_queue_create函数创建自定义的GCD
1
2
3
4
5
|
dispatch_queue_t custom_queue = dispatch_queue_create(“customQueue”, NULL);
dispatch_async(custom_queue, ^{
//doing something in custom_queue
});
dispatch_release(custom_queue);
|
4、线程合并
利用GCD并行多个线程并且等待所有线程结束之后再执行其它任务
1
2
3
4
5
6
7
8
9
10
|
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程一
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程二
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 汇总结果
});
|