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

iOS- GCD总结

2015-12-23 00:00 525 查看
GCD是iOS多线程中最常用的一种。需要明确的几点:

任务:block

队列:把任务放到队列里,队列先进先出的原则。

串行队列:顺序,一个一个执行。

并发队列:同时,同时执行很多个任务。

GCD中有俩个用来执行任务的函数。GCD里面的函数都是以dispatch开头的

用同步的方式执行任务: dispatch_sync(对列, block);不会开启新线程,在当前线程执行

用异步的方式执行任务:dispatch_async(对列, block);肯定会开新线程,在新线程中执行。

队列与同步异步的的组合方式共四类:分别看一下:

如果是串行队列,sync同步方法的话,一般只要使用“同步”执行,串行队列添加的同步任务,会立马执行,与不用GCD的顺序是一样的。

如果是串行队列,async异步执行的话,只会开一个新线程,而且所有任务都在这个新的线程里面一个一个顺序执行。

如果是并发队列,sync同步执行的话,不开新线程,顺序执行。与不用线程一样。

如果是并发队列,async异步执行的话,会开很多个线程,并发(不一定是一个一个的)执行。

总之如果是在同步的情况下,那么是不会开线程的,就是说同步的情况下多线程就失去了意义,只有异步的情况下才开线程。

同步和异步决定了要不要开启新的线程

同步:在当前线程中执行任务,不具备开启新线程的能力

异步:在新线程中执行任务,具备开启新线程的能力。

并发和串行决定了任务的执行方式

并发:多个任务并发(同时)执行

串行:一个任务执行完毕后,再执行下一个任务

总结;开不开线程,由执行的方法决定,同步不开,异步肯定开,开多少线程,由队列决定,串行,最多开一个线程,并发,可以开多个,具体开多少个,由GCD底层决定,程序控制不了。

主队列;专门负责在主线程上调度任务,主队列:特点,不允许开新线程,异步执行:会开新线程,在新线程执行,如果在主线程异步方法的话,不开新线程,没有作用,相当于把任务放到主队列,但不需要马上执行,等主队列空闲下来在执行。
如果在主队列同步方法的话,不开新线程,把任务放到主队列,但需要马上执行,这会造成死锁现象。
一。实现,用法
1.create方法创建队列dispatch queue

1.1 创建一个串行队列:参数:队列标签,队列属性

//属性标签DISPATCH_QUEUE_SERIAL or NULL
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);


1.2创建一个并行队列:

dispatch_queue_t myConcurrrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);

1.3异步实现

dispatch_async(myConcurrrentDispatchQueue, ^{
NSLog(@"block on myConcurrentDispatchQueue");
});

2.get方法创建队列dispatch queue

2.1系统标准提供的dispatch_queue,主队列,全局队列的创建:

/*
系统标准提供的dispatch_queue,主队列,全局队列
*/
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
dispatch_queue_t globalDispatchQueueHign = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t globalDiaptchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

2.2调用

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

/*
可并行执行的处理
*/
dispatch_async(dispatch_get_main_queue(), ^{

/*
在主线程中执行的处理
*/
});

});

3

3.1 modify the priority of queue after which is created

dispatch_queue_t mySerialDispatchQueue1 = dispatch_queue_create("mySerialDispatchQueue1", NULL);
dispatch_queue_t globalDispatchQueueBackgroud = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(mySerialDispatchQueue1, globalDispatchQueueBackgroud);
//dispatch_queue_create函数生成的队列不管是串行还是并行的,队列,都是用与默认优先级Global Dispatch Queue相同执行优先级的线程。而改变已有queue(队列)的执行优先级要用dispatch_set_target_queue函数。第一个参数指数要变更的队列来,第二个参数取其优先级给第一个,函数执行完后第一个参数的队列的优先级和第二个参数的优先级相同,第二个参数不变。第一个参数如果制定系统提供的Main Dispatch Queue和Global Dispatch Queue则不知道会出现什么状况,因此这些均不可指定。


3.2 在指定时间后把block追加到队列中,而不是在指定时间后开始执行block,具体何时开始执行由CPU调度决定。

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"waited at least three seconds");
});

3.3 Group(DISPATCH_QUEUE_CONCURRENT时,在追加到调度队列中的多个处理全部结束后想执行结束处理使用)

dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue1, ^{

});
dispatch_group_async(group, queue1, ^{

});
dispatch_group_async(group, queue1, ^{

});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//上面的queue1中的block全部执行完毕,就会执行这个方法中的block
});

//    dispatch_group_wait(<#dispatch_group_t group#>, <#dispatch_time_t timeout#>)

3.4 dispatch_barrier_async 数据库访问和文件访问

dispatch_queue_t queue = dispatch_queue_create("xom.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{

});
dispatch_async(queue, ^{

});
// 上面的并行处理全部完成后才会执行下面的,
dispatch_barrier_async(queue, ^{

});
// s上面的dispatch_barrier_async里的方法完全执行完毕后才会执行下面的方法,下面的方法又开始并行执行。
dispatch_async(queue, ^{

});
dispatch_async(queue, ^{

});

3.5 dispatch_walltime函数用于计算绝对时间,使用struct timespec 类型的时间得到dispatch_time_t 类型的值。而struct timespec类型的时间可以很轻松的通过NSDate类对象生成

//下面函数可由NSDate类对象获取能传递给dispatch_after函数的dispatch_time_t类型的值。
dispatch_time_t getDispatchTimeByDate(NSDate *date) {
NSTimeInterval interval;
double second, subsecond;
struct timespec time;
dispatch_time_t millestone;

interval = [date timeIntervalSince1970];
subsecond = modf(interval, &second);
time.tv_sec = second;
time.tv_nsec = subsecond *NSEC_PER_SEC;
millestone = dispatch_walltime(&time, 0);

return millestone;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: