GCD详细使用笔记
第一、通过GCD创建队列(Queue)
创建队列方式有以下几种:
1、创建一个串行队列:
1 dispatch_queue_t queue =dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL);
2、创建一个并行队列:
1 dispatch_queue_t queue =dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT);
3、获取一个全局的队列:
1 // 第1个参数表示队列执行的优先级: 2 // DISPATCH_QUEUE_PRIORITY_HIGH-高优先级 3 // DISPATCH_QUEUE_PRIORITY_DEFAULT-中优先级 4 // DISPATCH_QUEUE_PRIORITY_LOW-低优先级 5 // DISPATCH_QUEUE_PRIORITY_BACKGROUND-最低优先级 6 // 第2个参数暂不支持,传0即可; 7 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
4、获取一个运行在主线程中的队列:
1 dispatch_queue_t queue = dispatch_get_main_queue();
第二、队列的使用
1、执行一个串行队列:串行队列的特点是当前一个任务执行完毕后,后一个任务才开始执行。
1 dispatch_queue_t queue =dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL); 2 3 dispatch_async(queue, ^{ 4 5 NSLog(@"任务1 start"); 6 sleep(4); 7 NSLog(@"任务1 end"); 8 }); 9 10 dispatch_async(queue, ^{ 11 12 NSLog(@"任务2 start"); 13 sleep(2); 14 NSLog(@"任务2 end"); 15 });
2、执行一个并行队列:并行队列的特点是可以同时执行多个任务,在执行并行队列的时候,利用了信号量来控制同时执行的线程个数。
1 dispatch_queue_t queue =dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT); 2 dispatch_semaphore_t semaphore =dispatch_semaphore_create(2);//这里指定可以同时执行的任务个数 3 4 dispatch_async(queue, ^{ 5 6 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 7 NSLog(@"任务1 start"); 8 sleep(4); 9 NSLog(@"任务1 end"); 10 dispatch_semaphore_signal(semaphore); 11 }); 12 13 dispatch_async(queue, ^{ 14 15 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 16 NSLog(@"任务2 start"); 17 sleep(3); 18 NSLog(@"任务2 end"); 19 dispatch_semaphore_signal(semaphore); 20 }); 21 22 dispatch_async(queue, ^{ 23 24 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 25 NSLog(@"任务3 start"); 26 sleep(8); 27 NSLog(@"任务3 end"); 28 dispatch_semaphore_signal(semaphore); 29 }); 30 dispatch_async(queue, ^{ 31 32 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 33 NSLog(@"任务4 start"); 34 sleep(6); 35 NSLog(@"任务4 end"); 36 dispatch_semaphore_signal(semaphore); 37 });
3、执行一个并行队列:上面我们已经讲述了如何执行一个并行队列,并且指定并行任务最大个数,那么下面还有一个方法可以实现,就是利用
dispatch_barrier_async(并行队列中设置分界线),分界线的作用就是,将一组并行任务切割成多组并行任务顺序执行。我们也经常使用它来解决由于并发导致的数据不同步问题。
1 dispatch_queue_t queue = dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT); 2 3 dispatch_async(queue, ^{ 4 5 NSLog(@"任务1 start"); 6 sleep(4); 7 NSLog(@"任务1 end"); 8 }); 9 10 dispatch_async(queue, ^{ 11 12 NSLog(@"任务2 start"); 13 sleep(3); 14 NSLog(@"任务2 end"); 15 }); 16 17 dispatch_barrier_async(queue, ^{ 18 19 NSLog(@"--------------前面的并发任务执行完毕,准备执行下面的并发任务--------------"); 20 sleep(2); 21 }); 22 23 dispatch_async(queue, ^{ 24 25 NSLog(@"任务3 start"); 26 sleep(2); 27 NSLog(@"任务3 end"); 28 }); 29 30 dispatch_barrier_async(queue, ^{ 31 32 NSLog(@"--------------前面的并发任务执行完毕,准备执行下面的并发任务--------------"); 33 sleep(2); 34 }); 35 36 dispatch_async(queue, ^{ 37 38 NSLog(@"任务4 start"); 39 sleep(5); 40 NSLog(@"任务4 end"); 41 }); 42 dispatch_async(queue, ^{ 43 44 NSLog(@"任务5 start"); 45 sleep(3); 46 NSLog(@"任务5 end"); 47 }); 48 dispatch_async(queue, ^{ 49 50 NSLog(@"任务6 start"); 51 sleep(5); 52 NSLog(@"任务6 end"); 53 });
4、执行一个串行队列,并且我想知道这组队列什么时候执行完毕:
1 dispatch_queue_t queue =dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL); 2 dispatch_group_t group =dispatch_group_create(); 3 dispatch_group_async(group, queue, ^{ 4 NSLog(@"任务1 start"); 5 sleep(2); 6 NSLog(@"任务1 end"); 7 }); 8 dispatch_group_async(group, queue, ^{ 9 NSLog(@"任务2 start"); 10 sleep(2); 11 NSLog(@"任务2 end"); 12 }); 13 dispatch_group_async(group, queue, ^{ 14 NSLog(@"任务3 start"); 15 sleep(2); 16 NSLog(@"任务3 end"); 17 }); 18 19 // //方法一: 20 // dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 21 // //这里会等待group中的所有任务执行完成后才会向下执行 22 // NSLog(@"所有任务全部执行完毕"); 23 24 //方法二: 25 dispatch_group_notify(group, queue, ^{ 26 27 NSLog(@"所有任务全部执行完毕"); 28 }); 29 //这里不会等到group中所有的任务执行完成后才会向下执行 30 NSLog(@"所有任务还没执行完毕");
5、执行一个并行队列,并且我想知道这组队列什么时候执行完毕:
1 dispatch_queue_t queue =dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT); 2 dispatch_semaphore_t semaphore =dispatch_semaphore_create(2);//这里指定可以同时执行的任务个数 3 dispatch_group_t group =dispatch_group_create(); 4 dispatch_group_async(group, queue, ^{ 5 6 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 7 NSLog(@"任务1 start"); 8 sleep(7); 9 NSLog(@"任务1 end"); 10 dispatch_semaphore_signal(semaphore); 11 }); 12 dispatch_group_async(group, queue, ^{ 13 14 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 15 NSLog(@"任务2 start"); 16 sleep(5); 17 NSLog(@"任务2 end"); 18 dispatch_semaphore_signal(semaphore); 19 }); 20 dispatch_group_async(group, queue, ^{ 21 22 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 23 NSLog(@"任务3 start"); 24 sleep(3); 25 NSLog(@"任务3 end"); 26 dispatch_semaphore_signal(semaphore); 27 }); 28 dispatch_group_async(group, queue, ^{ 29 30 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 31 NSLog(@"任务4 start"); 32 sleep(2); 33 NSLog(@"任务4 end"); 34 dispatch_semaphore_signal(semaphore); 35 }); 36 37 // //方法一: 38 // dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 39 // //这里会等待group中的所有任务执行完成后才会向下执行 40 // NSLog(@"所有任务全部执行完毕"); 41 42 //方法二: 43 dispatch_group_notify(group, queue, ^{ 44 45 NSLog(@"所有任务全部执行完毕"); 46 }); 47 //这里不会等到group中所有的任务执行完成后才会向下执行 48 NSLog(@"所有任务还没执行完毕");
第三、利用GCD实现单例模式
1 - (MySingletonObj *)shareObj{ 2 3 static MySingletonObj *singleton; 4 static dispatch_once_t onceToken; 5 dispatch_once(&onceToken, ^{ 6 //这里在整个程序的生命周期内只会执行一次 7 singleton =[[MySingletonObj alloc] init]; 8 }); 9 return singleton; 10 }
第四、利用GCD实现一个定时任务
1 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 2 3 NSLog(@"3秒钟到了,我开始执行了"); 4 });
第五、利用GCD实现一个循环操作:这个方法是同步运行的,类似于for循环
1 dispatch_queue_t queue =dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL); 2 // dispatch_queue_t queue =dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT); 3 dispatch_apply(5, queue, ^(size_t index) { 4 5 //注意:如果queue是串行队列,那么index是按照0、1、2、3、4的顺序执行 6 // 如果queue是并行队列,那么index就不一定是按照顺序执行了 7 NSLog(@"%@", @(index)); 8 });
第六、某些情况下,我们可能会想让Queue暂时停止一下,然后在某个时刻恢复处理,这时就可以使用dispatch_suspend以及dispatch_resume函数。暂停时,如果已经有block正在执行,那么不会对该block的执行产生影响。dispatch_suspend只会对还未开始执行的block产生影响。
1 //暂停 2 dispatch_suspend(globalQueue) 3 //恢复 4 dispatch_resume(globalQueue)
第七、设置队列的优先级
iOS8之后:
dispatch_qos_class_t qosClass = QOS_CLASS_UTILITY; // qos指定优先级,包括如下(又高到底): /** QOS_CLASS_USER_INTERACTIVE QOS_CLASS_USER_INITIATED QOS_CLASS_UTILITY QOS_CLASS_BACKGROUND QOS_CLASS_DEFAULT */ dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0); return dispatch_queue_create(label, attr);
iOS8之前:
long identifier = DISPATCH_QUEUE_PRIORITY_HIGH; // identifier优先级,包括(由高到低): /** DISPATCH_QUEUE_PRIORITY_HIGH DISPATCH_QUEUE_PRIORITY_LOW DISPATCH_QUEUE_PRIORITY_BACKGROUND DISPATCH_QUEUE_PRIORITY_DEFAULT */ dispatch_queue_t queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL); dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));
以上是关于GCD中常用的一些函数和用法,其他方面有兴趣的可以到官网了解具体使用。
要得到你必须要付出,要付出你还要学会坚持,如果你真的觉得很难,那你就放弃,但是你放弃了就不要抱怨,我觉得人生就是这样,世界真的是平等的,每个人都要通过自己的努力,去决定自己生活的样子。