GCD
1、定义:
Grand Central Dispatch;
iOS的一种底层多线程机制;
多核编程的解决方法;
使用内联的形式,将block代码,放置其中;
GCD可以说是依赖于Block,了解:Block
2、控制:
dispatch_async(queue, block);
其中 queue 队列,系统提供两种, 一种是串行队列( SerialDispatchQueue ),一种是并行队列( ConcurrentDispatchQueue );
block 是其中的代码块,queue 队列控制block的使用形式;
3、MainDispatchQueue:
将任务插入主线程的RunLoop当中去执行,是个串行队列;
可以使用它来更新UI;
获取主线程队列:
dispatch_queue_t queue = dispatch_get_main_queue();
简略的执行:
// 主线程执行:
dispatch_async(dispatch_get_main_queue(), ^{
// something
});
4、GlobalDispatchQueue:
是一个全局的并行队列,有高、默认、低和后台4个优先级;
可以并发地执行多个任务;
DISPATCH_QUEUE_PRIORITY_HIGHT、
DISPATCH_QUEUE_PRIORITY_DEFAULT、
DISPATCH_QUEUE_PRIORITY_LOW、
DISPATCH_QUEUE_PRIORITY_BACKGROUND、
获取全局队列:
dispatch queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0)
简略的执行:( 并行三个任务队列)
// 后台执行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
// 后台执行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
// 后台执行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
5、SerialDispatchQueue:
串行队列;
用于按顺序同步访问,可创建任意数量的串行队列,各个串行队列之间是并发的。
线程池只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束才能开始。
创建串行队列:
dispatch_queue_t myQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
执行:
//串行队列
dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{
// do something
});
dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{
// do something
});
dispatch_async 可以去执行多个来验证是否是串行的;
6、普遍用法:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 做一些耗时操作
dispatch_async(dispatch_get_main_queue(), ^{
// update UI
});
});
7、执行一次的队列:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shareInstance = [[self alloc] init];
});
可以保证整个应用程序生命周期中某段代码只被执行一次!
适用于:单利模式
8、延迟执行:
// 延迟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
});
9、多次执行:
执行某个代码片段N次。
int n=5;
dispatch_apply(n, globalQ, ^(size_t index) {
// 执行5次
});
其中的队列,
可以是串行,也可以是并行队列;
10、组任务:
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, ^{
});
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"main thread.");
});
并行三个任务处于一个组中,组中任务执行完成后通知;
11、并发安全性:
在并发执行时的数据读取和写入,需要考虑数据的安全性;
由于dispatch_get_global_queue 无法控制其中的队列,那么如何做呢?
dispatch_barrier_async
在前面的队列执行完成之后,才会继续下面的队列;
dispatch_queue_t queue = dispatch_queue_create("com.qb.queue.GCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
});
dispatch_async(queue, ^{
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
});
dispatch_async(queue, ^{
});
12、优先级:
通过dispatch_set_target_queue函数可以设置一个dispatch queue的优先级;
或者指定一个dispatch source相应的事件处理提交到哪个queue上。
dispatch_queue_t currentQueue = dispatch_queue_create("com.qb.demo.GCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t targetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(currentQueue, targetQueue);
13、最后:
在没有使用GCD时,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。
在使用GCD后,app最多有10分钟的时间在后台长久运行。
这个时间可以用来做清理本地缓存,发送统计数据等工作。
即:GCD的另一个用处是可以让程序在后台较长久的运行。
(摘自网上,待验证)
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self beingBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask {
self.backgroundUpdateTask = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void)endBackgroundUpdateTask {
}