您的位置:首页 > 移动开发 > IOS开发

iOS多线程中GCD的使用

2015-10-05 21:49 363 查看
Grand Central Dispatch 简称(GCD),是苹果公司开发的技术。以后话应用程序支持多核心处理器和其他对称多处理系统的系统。GCD属于函数级多线程,性能更高,功能更强大。它首次发布在OS X 10.6。iOS 4.0及以上也可以使用。

·任务:具有一定功能的代码段。一般是一个block或者函数。
·分发队列:GCD以队列的方式进行工作,遵循FIFO(first in first out)
·CGD会根据分发队列的类型,创建合适的数量的线程来执行队列中的任务。


·主队列:串行队列
·全局队列:并行队列
·自定义队列:[串行队列 或 并行队列]
·主队列和全局队列均为单例


GCD中两种队列(dispatch queue):

1,SerialQueue:一次只执行一个任务。SerialQueue通常用于同步访问特定的资源或数据。当你创建多个SerialQueue时,虽然他们各自是同步执行的,但SerialQueue与SerialQueue之间是并发执行的。SerialQueue能实现线程同步

2,Concurrent:可以并发地执行多个任务,但是遵循FIFO。

dispatch_async() //将任务添加到队列中,任务会排队执行
//dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_after() //将任务添加到队列中,任务会按照延迟时间点排队执行
//dispatch_after(<#dispatch_time_t when#>, <#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_apply() //将任务添加到队列中,任务会重复执行n次
//dispatch_apply(<#size_t iterations#>, <#dispatch_queue_t queue#>, <#^(size_t)block#>)

dispatch_group_async()    //将任务添加到队列中,并添加分组标记
//dispatch_group_async(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_group_notify()   //将任务添加到队列中,并且按照添加进入组的顺序执行
//dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_barrier_async()  //将任务添加到队列中,此任务执行的时候,阻塞其他任务执行,用在“自定义并行队列中”
//dispatch_barrier_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_once() //将任务添加到队列中,但任务在程序运行过程中只执行一次
//dispatch_once(<#dispatch_once_t *predicate#>, <#^(void)block#>)

dispatch_sync() //将任务添加到队列中,执行完block中的代码才会执行此函数下面的代码(同步)
//dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)

dispatch_async_f() //将任务添加到队列中,任务是函数非block
//dispatch_async_f(<#dispatch_queue_t queue#>, <#void *context#>, <#dispatch_function_t work#>)


获取主队列

dispatch_queue_t mainQueue = dispatch_get_main_queue();
//结构相当于 int a = 10;


向队列中添加任务:

dispatch_async(mainQueue,^{
NSLog(@"Erica");//此处可调用方法
});
dispatch_asyna(mainQueue,^{
NSLog(@"Lake");
});
//请勿将延时(dispatch_after()) 或 任务重复(dispatch_apply())添加在主线程中,可能会造成主线程阻塞,程序卡死


全局队列

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORY_DEFAULT,0);
//上面第一个参数:
//#define DISPATCH_QUEUE_PRIORITY_HIGH 2      优先级高
//#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认优先级
//#define DISPATCH_QUEUE_PRIORITY_LOW (-2)  优先级低
//#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 优先级最低(后台)


向队列中添加任务

dispatch_async(globalQueue,^{
NSLog(@"Erica");
});

dispatch_apply(10,globalQueue,^(size_t times){
//注意,block中times参数是由我们添加上去的,否则编译器会丢出警告。
//此block中的内容会执行10次,也就是函数的第一个参数决定的。
});


分组任务

dispatch_group_t group = dispatch_group_create();//创建一个分组

dispatch_group_async(group,globalQueue,^{
//任务
});
dispatch_group_notify(group,globleQueue,^{
//此函数会按照添加进入分组队列的顺序来执行(因为并行,他之外的任务几乎是同时执行的)
});


自定义队列

dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent",DISPATCH_QUEUE_CONCURRENT);
//·第一个参数为队列标识符
const char *flag = dispatch_queue_get_label(concurrentQueue);//通过此方法可以获得serialQueue队列的标识符
//·第二个参数为队列类型
//DISPATCH_QUEUE_SERIAL 串行队列
//DISPATCH_QUEUE_CONCURRENT 并行队列


向自定义队列中添加任务

dispatch_async(concurrentQueue,^{
//任务
});

dispatch_barrier_async(concurrentQueue,^{
//次任务执行时,阻塞其他任务执行。
});

dispatch_sync(concurrentQueue,^{
//此任务执行时,其他任务不执行,为同步任务。(安全性高)
});


GCD可以向队列中添加函数

//(在方法外)定义一个函数并实现:必须为void(*)(void *)类型的函数
void function(void *aString);
void function(void *aString){
NSLog(@"%s",aString);
}

//将函数添加到队列中:
dispatch_sync_f(concurrentQueue,"参数",function);
//运行结果:控制台打印“参数”


添加单例任务

static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//由&onceToken标记的任务仅执行一次。
});
dispatch_once(&onceToken,^{
//由于上面已经添加了标记为onceToken的任务,所以次任务不会执行了。
});


所以我们可以用这个特性来写单例类,保证线程安全

//比如我们自定义一个SingletonClass类有一个单例方法叫做share
@implementation SingletonClass

+ (instancetype)share{
static SingletonClass *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [self new];
});
return singleton;
}

@end


当然单单写一个share方法来创造单例对象是不够全面的。如果团队中其他人不知道你写的这个类有单例方法,而采用new / alloc] init 等方法创建对象,那么对象当然就不会是单例了。所以我们还需要重写 - init 等方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: