GCD学习小结

2017-04-26  本文已影响4人  凸阿滨

一)简介

Serial Dispatch Queue要求等待正在执行的任务完成,再执行下一个。而Concurrent Dispatch Queue中后面的任务可以不必等待正在执行的任务执行完成就可以开始执行,也就是同时可以执行多个任务。换句话说,其实就是Serial Dispatch Queue只会创建一个线程来执行任务,而Concurrent Dispatch Queue会创建多个线程同时执行多个任务。

名词定义:Serial Dispatch Queue串行代码;Concurrent Dispatch Queue并行代码。

(二)队列创建

1 串形队列创建

dispatch_queue_t serialQueue =

dispatch_queue_create("com.SerialQueue" ,NULL);

2 并形队列创建

dispatch_queue_t concurrentQueue =

dispatch_queue_create("com.ConcurrentQueue",

DISPATCH_QUEUE_CONCURRENT);

3 dispatch_sync同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行。

dispatch_queue_t concurrentQueue =dispatch_queue_create("my.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);

NSLog(@"1");

dispatch_sync(concurrentQueue, ^(){

NSLog(@"2");

[NSThreadsleepForTimeInterval:10];

NSLog(@"3");

});

NSLog(@"4");

输出:1234

4 dispatch_async ,异步添加进任务队列,它不会做任何等待

dispatch_queue_t concurrentQueue =dispatch_queue_create("my.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);

NSLog(@"1");

dispatch_async(concurrentQueue, ^(){

NSLog(@"2");

[NSThreadsleepForTimeInterval:5];

NSLog(@"3");

});

NSLog(@"4");

输出:1423

Concurrent Dispatch Queue不过创建多少都没有问题,因为Concurrent Dispatch Queue所使用的线程由系统的XNU内核高效管理,不会影响系统性能。

对于串行队列,每创建一个串行队列,系统就会对应创建一个线程,同时这些线程都是并行执行的,只是在串行队列中的任务是串行执行的。大量的创建串行队列会导致大量消耗内存,这是不可取的做法。串行队列的优势在于他是一个线程,所以在操作一个全局数据时候是线程安全的。当想并行执行而不发生数据竞争时候可以用并行队列操作

(三)Main&Global Dispatch Queue

Main Dispatch Queue是在主线程中执行任务的Dispatch Queue。因为主线程只有1个,所以Main Dispatch Queue是Serial Dispatch Queue。追加到Main Dispatch Queue中的任务将在主线程的RunLoop中执行。因为是在主线程中执行,所以应该只将用户界面更新等一些必须在主线程中执行的任务追加到Main Dispatch Queue中。

dispatch_queue_t dispatch_main_queue =dispatch_get_main_queue();

Global Dispatch Queue是所有应用程序都能使用的Concurrent Dispatch Queue。大多数情况下,可以不必通过dispatch_queue_create函数生成Concurrent Dispatch Queue,而是只要获取Global Dispatch Queue使用即可。Global Dispatch Queue有4个优先级,分别是:High、Default、Low、Background。

dispatch_queue_t dispatch_global_queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

(四)线程组dispatch_group

1:实现

如果想在dispatch_queue中所有的任务执行完成后在做某种操作,在串行队列中,可以把该操作放到最后一个任务执行完成后继续,但是在并行队列中怎么做呢。这就有dispatch_group 成组操作。比如

dispatch_queue_t dispatchQueue =dispatch_queue_create("ted.queue.next",DISPATCH_QUEUE_CONCURRENT);

dispatch_group_t dispatchGroup =dispatch_group_create();

dispatch_group_async(dispatchGroup, dispatchQueue, ^(){

NSLog(@"dispatch-1");

});

dispatch_group_async(dispatchGroup, dispatchQueue, ^(){

NSLog(@"dspatch-2");

});

dispatch_group_notify(dispatchGroup,dispatch_get_main_queue(), ^(){

NSLog(@"end");

});

上面的 log1 和log2输出顺序不定,因为是在并行队列上执行,当并行队列全部执行完成后,最后到main队列上执行一个操作,保证“end”是最后输出。 另外,这里也可以不用创建自己的并行队列,用全局的global,那个也是个并行队列. dispatch_get_gloable_queue(0,0);

2:实现

以上方法有一个问题就是在任务1没有执行完回调之后就认为任务全部处理完成执行输出“end”

dispatch_group_t group =dispatch_group_create();

dispatch_group_enter(group);

// 任务代码1

dispatch_group_leave(group);

// 回调执行1

dispatch_group_enter(group);

// 任务代码2

dispatch_group_leave(group);

// 回调执行2

dispatch_group_notify(group,dispatch_get_main_queue(), ^{

// 主线程处理 全部完成

});

在任务开始前 调用 enter,任务完成时调用leave,直到它发现group里面的任务全部leave(也就是所有任务的回调都执行完成后),它才放弃阻塞(任务全部完成),然后我们在主线程更新UI告知用户.

(五)dispatch_barrier_async

dispatch_queue_t concurrentQueue =dispatch_queue_create("my.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-1");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-2");

});

dispatch_barrier_async(concurrentQueue, ^(){

NSLog(@"dispatch-barrier");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-3");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-4");

});

dispatch_barrier_async 作用是在并行队列中,等待前面两个操作并行操作完成,这里是并行输出dispatch-1,dispatch-2

然后执行dispatch_barrier_async中的操作,(现在就只会执行这一个操作)执行完成后,即输出"dispatch-barrier,

最后该并行队列恢复原有执行状态,继续并行执行dispatch-3,dispatch-4

上一篇下一篇

猜你喜欢

热点阅读