iOS开发多线程GCD(二)

笑着哭i 提交于 2019-12-05 20:10:46

上一章我们简单介绍了iOS多线程,本章我们讲解GCD多线程

GCD (Grand Central Dispatch) 是 iOS 多任务的核心。在 Mac OS X 10.6 雪豹中首次推出,后被引入到了 iOS 4.0 中。GCD 是基于 C 的 API,是底层的框架,因此效率最高

一、分组管理

/*
     分组的主要目的 是判断一组操作 是否全部执行结束
     原理 将需要执行的操作 添加到同一个分组下 如果其中的某一个操作结束 就会组中移除 当组里面的操作数变为0的 说明所以的操作全部结束
     */
    //1.创建一个分组 管理任务
    dispatch_group_t myGroup = dispatch_group_create();
    
    //2.获取一个队列 管理的任务放在哪一个线程中来管理
    //主队列就表示任务放在主线程中 自定义队列就表示任务放在分线程中(子线程)
    
    //dispatch_queue_t 表示一个队列表示获取一个队列表示获取一个队列全局队列 官方提供一个队列 该队列 默认的是并发处理 线程中的任务可以同时处理多个全局队列 官方提供一个队列 该队列 默认的是并发处理 线程中的任务可以同时处理多个
    
    //dispatch_get_global_queue()
    
    dispatch_queue_t HIGH = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_queue_t DEFAULT = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t LOW = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_queue_t BACKGROUN = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    //0 系统要求填入一个标志符 必须是0 但是实际这个0 并没有什么用 不填系统不会讲相应的队列返回 直接返回空
    
    //3.通过队列执行一个任务 这个任务是在分组中异步执行
    dispatch_group_async(myGroup, BACKGROUN, ^{
        for(int i = 0; i < 5; i++){
            NSLog(@"DISPATCH_QUEUE_PRIORITY_BACKGROUND");
        }
    });
    
    dispatch_group_async(myGroup, LOW, ^{
        for(int i = 0; i < 5; i++){
            NSLog(@"DISPATCH_QUEUE_PRIORITY_LOW");
        }
    });
    
    dispatch_group_async(myGroup, DEFAULT, ^{
        for(int i = 0; i < 5; i++){
            NSLog(@"DISPATCH_QUEUE_PRIORITY_DEFAULT");
        }
    });
    
    dispatch_group_async(myGroup, HIGH, ^{
        for(int i = 0; i < 5; i++){
            NSLog(@"DISPATCH_QUEUE_PRIORITY_HIGH");
        }
    });
    
    //dispatch_group_notify()表示一个通知 分组中所有任务执行结束的通知
    //dispatch_get_main_queue() 获取主队列
    dispatch_group_notify(myGroup, dispatch_get_main_queue(), ^{
        NSLog(@"分组中所有任务执行结束");
        
    });
    
    /*
     总结:分组中管理的任务并发执行 执行结束的通知方法应该交给主队列来管理 由主线程来执行
     注意:在指定优先级之后,同一个队列会按照这个优先级执行,当然这不是串行队列,所以不存在绝对回调先后,打印控制台不一定是按照严格的顺序显示
     */


二、自己创建队列进行管理

    //1.创建一个队列
    dispatch_queue_t myQueue = dispatch_queue_create("MY_QUEUE", DISPATCH_QUEUE_SERIAL);
    //参数一:C字符串 队列名
    //参数二:队列中执行的方式 DISPATCH_QUEUE_SERIAL 串行 DISPATCH_QUEUE_CONCURRENT并行
    //2.在队列中管理一个异步操作
    dispatch_async(myQueue, ^{
        for (int i = 0; i < 5; i++) {
             NSLog(@"我爱你中国!");
        }
    });
    
    dispatch_async(myQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"打死小日本");
        }
    });
    
    dispatch_async(myQueue, ^{
        NSLog(@"执行结束!");
    });
    //总结:如果一个队列设置的执行方式是串行 使用GCD异步执行 不会影响队列内部执行的顺序
    

三、获取主队列

dispatch_queue_t mainQueue = dispatch_get_main_queue();

四、暂停队列与恢复队列

/*
    dispatch_suspend(myQueue);//暂停一个队列
    
    //如果暂停一个队列不要忘记恢复。暂停和恢复的操作和内存管理中的retain和release类似。调用dispatch_suspend会增加暂停计数,而dispatch_resume则会减少。队列只有在暂停计数变成零的情况下才开始运行。
    dispatch_resume(myQueue);//恢复一个队列如果不恢复程序会崩溃
     */
    dispatch_queue_t queue = dispatch_queue_create("com.test.gcd", DISPATCH_QUEUE_SERIAL);
    //提交第一个block,延时5秒打印。
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"After 5 seconds...");
    });
    //提交第二个block,也是延时5秒打印
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"After 5 seconds again...");
    });
    //延时一秒
    NSLog(@"sleep 1 second...");
    sleep(1);
    //挂起队列
    NSLog(@"suspend...");
    dispatch_suspend(queue);
    //延时10秒
    NSLog(@"sleep 10 second...");
    sleep(10);
    //恢复队列
    NSLog(@"resume...");
    dispatch_resume(queue);

五、GCD实用。

// 主线程执行:多用户返回主线程
 dispatch_async(dispatch_get_main_queue(), ^{
      // something
 });

 // 一次性执行:例如单例
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
     // code to be executed once
 });

另外GCD多线程可以处理程序耗时操作防治程序假死,例如下载文件

GCD的另一个用处是可以让程序在后台较长久的运行。

在没有使用GCD时,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是在使用GCD后,app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!