GCD 使用指南

发布于 2015-08-03 06:13 1149 字 6 min read

前端项目通过bridge获取客户端资源,客户端直接返回response对象Win11 光标变白消失解决方案(浏览器开启硬件加速后,在鼠标滑到文本处出现)Terminal里用option/alt + 鼠标点击,就可以让光标到指定位置Duff's Device为 UIControl 实现线程安全的 Block 事件扩展:原理与实践前端代码规范设计模式k8s前端项目利用nginx部署项目不停机Vue3+Vite+history模式+Nginx 部署二级路径iOS开发工具常用代码模板2——数据结构常用代码模板1——基础算法iOS:特殊符号大全HomeBrew 更新报错“fatal- Could not resolve HEAD to a revision”SwiftUI基本控件代码大全——1.欢迎进入软件构建的世界C++ STL简介LeetCode 70 爬楼梯(青蛙跳台阶)深入理解计算机系统(第二版) 家庭作业 第二章Swift Module 如何被全局引用LeetCode 398 随机数索引Vue 的一些指令和缩写LeetCode 486 Predict the Winner(预测赢家)浅谈iOS中的weakCocoaPods组件化——OC/Swift动静态库混用OpenGL 术语当对象接收到不能处理的消息时调用的方法命令行通过ffmpeg剪切视频iOS:如何在UITableView调用reloadData刷新结束后再同步执行后续操作统计iOS工程代码行数CMake 入门及常用变量指令手册LeetCode 6 ZigZag Conversion(Z字转换)LeetCode 106 Construct Binary Tree from Inorder and Postorder Traversal(由中序和后序遍历建立二叉树)LeetCode 5 Longest Palindromic Substring(最长回文字串)LeetCode 8 String to Integer (atoi)Objective-C Type EncodingsObjective-C:为什么分类中不能直接添加属性MeshLab数据结构与算法解析习题2.23数据结构与算法解析习题2.19数据结构与算法解析习题2.16数据结构与算法解析习题2.14数据结构与算法解析习题2.13数据结构与算法解析习题2.12数据结构与算法解析习题2.11:二分查找数据结构与算法解析习题2.10:霍纳法则(Horner's rule)数据结构与算法解析习题2.7数据结构与算法解析习题1.3数据结构与算法解析习题1.2数据结构与算法解析习题1.1centos7 mysql数据库安装和配置Fishhook-源码分析解决Mac下 Cornerstone 无法查看SVN日志的问题UIButton扩大点击范围以及关于响应者链条的思考UILabel中文带行间距的处理,限制行数,计算高度等UITableview调用reload方法时抖动问题C语言指针小结C语言数据类型和const、static关键字iOS 截取整个 scrollview 图片WxWidgets类列表objc源码分析-runtime-classiOS自动化埋点的实现iOS平台编译Ogre游戏引擎库在 Mac OS X 上安装 TensorFlowiPhone 刘海机型UI适配(X、Xs、Xs Max、Xr)关于C语言中的union虚拟机 Linux 上编 slice3r perl Build.PL 报错iOS 沙盒与 BundleCOCOAPODS技巧-创建私有仓库iOS脚本打包 ipa(.app转.ipa)Objective-C 中禁止调用指定的方法iOS 关于 UITextField 的字数限制升级 Mac OS 10.13 High Sierra 后 ruby 报错iOS 框架学习-AsyncSocketSQL语句OC优缺点以及常见bugUIViewController 的生命周期runtime——运行时简单使用iPhone6 Plus上面神秘的缝隙CocoaPods安装和使用教程(更新至Mac High Sierra)UIApplicationiOS 网络小结NSString的各种处理HTTP请求报文和HTTP响应报文,以及工作原理Vim 快捷键整理OC中nil 、NULL、 Nil 、NSNull的区别GCD 使用指南iOS常用数据类型转换关于NSNotificationCenterGit 命令MAC OS 常用技巧Description方法和NSLog函数代码重构OC单例宏Block in Objective-CObjective-C 语法 3Objective-C 语法 2Objective-C 语法 1
常规操作 1,/** 串行队列,同步的任务 */ // 1.创建串行队列,下面两种方式都可以 dispatch_queue_t q = dispatch_queue_create("itcast.download", DISPATCH_QUEUE_SERIAL); dispa

常规操作

1/** 串行队列,同步的任务 */
    // 1.创建串行队列,下面两种方式都可以
    dispatch_queue_t q = dispatch_queue_create("itcast.download", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t q = dispatch_queue_create("itcast.download", NULL);
    // 2. 添加任务
    for (int i = 0; i < 10; i++)
    {
        // 决定任务的类型:同步的/异步的
        // dispatch_sync     同步
        // dispatch_async    异步的
        dispatch_sync(q, ^
        {
            NSLog(@"下载图片 %@ %d", [NSThread currentThread], i);
        });
    }
    // 释放操作仅在 MRC中使用
    // dispatch_release(q);

2/** 串行队列,异步任务 */
    // 1. 队列
    dispatch_queue_t q = dispatch_queue_create("itcast.download", NULL);

    // 2. 任务
    for (int i = 0; i < 10; i++)
    {
        dispatch_async(q, ^
        {
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }
3/** 并发队列,异步任务 */
    // 1. 队列(并发) 先进先出
    dispatch_queue_t q = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);

    // 2. 任务
    // 具体在哪一条上面工作,程序员不用关心
    for (int i = 0; i < 100; i++)
    {
        dispatch_async(q, ^
        {
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }

4/** 并发队列,同步方法 */
    // 1. 队列(并发) 先进先出
    dispatch_queue_t q = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);

    // 2. 任务
    for (int i = 0; i < 10; i++)
    {
        dispatch_sync(q, ^
        {
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }
5/** 主队列,异步方法 */
    // 1. 队列
    dispatch_queue_t q = dispatch_get_main_queue();

    // 2. 异步方法
    for (int i = 0; i < 10; i++)
    {
         // 顺序执行的!
        dispatch_async(q, ^
        {
             NSLog(@"下载完成 %@ %d", [NSThread currentThread], i);
        });
    }
6/** 主队列,同步方法,会死锁!!! */
    // 1. 队列
    dispatch_queue_t q = dispatch_get_main_queue();

    // 2. 同步方法
    for (int i = 0; i < 10; i++)
    {
    // 顺序执行的!
        dispatch_sync(q, ^
        {
            NSLog(@"下载完成 %@ %d", [NSThread currentThread], i);
        });
    }
7#pragma mark - 同步方法的应用场景
    /** 同步方法只会用在并发队列中 */
    - (void)gcdDemo7
    {
        // 1. 队列
        dispatch_queue_t q = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);

        // 2. 添加任务
        /**
            下载付费小说
            1. 用户登录
            2. 下载小说(3)
        */

        dispatch_async(q, ^
        {
            NSLog(@"%@", [NSThread currentThread]);

            // 同步任务,在后台线程中,去阻塞住其他异步任务
            dispatch_sync(q, ^
            {
                NSLog(@"用户登录 %@", [NSThread currentThread]);
            });

            for (int i = 0; i < 3; i++)
            {
                dispatch_async(q, ^
                {
                    NSLog(@"下载小说 %d %@", i, [NSThread currentThread]);
                });
            }
        });
    }
8,全局队列
    #pragma mark - 全局队列
    // 全局队列是一个并发队列
    /**
    	和自己创建的队列的区别

    	1> 没有名字的区别,用于崩溃报告!
    	2> 在使用C语言框架时,通常创建对象的函数出现alloc,create,retain,copy单词,都需要考虑release

        不过在GCD中,ARC同样不需要release
        MRC使用dispatch_release释放对象
    */
    - (void)gcdDemo8
    {
        // 队列
        /**
        参数
         1> 优先级
         #define DISPATCH_QUEUE_PRIORITY_HIGH 2              高
         #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0           默认
         #define DISPATCH_QUEUE_PRIORITY_LOW (-2)               低
         #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN   后台

        面试题:GCD中真正一共有几个队列?(仅供参考!)

         1) 主队列
         2) 串行队列
         3) 高优先级并发队列
         4) 默认并发队列 => 用户创建的并发队列
         5) 低并发队列
         6) 后台并发队列
         2> 0
        */
        dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
            // 任务
        for (int i = 0; i < 10; i++)
        {
           dispatch_async(q, ^
           {
               NSLog(@"%@, %d", [NSThread currentThread], i
           );
        }

    }

其他用法

定时(延时)

dispatch_after( dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    <#code to be executed after a specified delay#>
});

 dispatch_after(<#dispatch_time_t when#>, <#dispatch_queue_t queue#>, <#^(void)block#>);

只执行一次

dispatch_once是线程安全的!并没有用到互斥锁!

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    <#code to be executed once#>
});
dispatch_once(<#dispatch_once_t *predicate#>, <#^(void)block#>);

等group队列中的所有任务都执行完毕, 再回到主线程执行其他操作

//创建一个组
dispatch_group_t group = dispatch_group_create();

// 开启一个任务下载图片1
__block UIImage *image1 = nil;
dispatch_group_async(group, global_queue, ^{
    image1 = [self imageWithURL:@"http://news.baidu.com/z/resource/r/image/2014-06-22/2a1009253cf9fc7c97893a4f0fe3a7b1.jpg"];
 });

// 开启一个任务下载图片2
__block UIImage *image2 = nil;
dispatch_group_async(group, global_queue, ^{
    image2 = [self imageWithURL:@"http://news.baidu.com/z/resource/r/image/2014-06-22/b2a9cfc88b7a56cfa59b8d09208fa1fb.jpg"];
 });

//同时执行下载图片1\下载图片2操作
等group中的所有任务都执行完毕, 再回到主线程执行其他操作
dispatch_group_notify(group, main_queue, ^{
    self.imageView1.image = image1;
    self.imageView2.image = image2;

    // 合并
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 100), NO, 0.0);
    [image1 drawInRect:CGRectMake(0, 0, 100, 100)];
    [image2 drawInRect:CGRectMake(100, 0, 100, 100)];
    self.bigImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
});

NSOperation & GCD 的区别

NSOperation

  1. 简单,基于GCD的面向对象封装
  2. 提供了简单的并发处理能力,不需要考虑(串行/并发)队列和(同步任务/异步任务)任务
  3. 特有的功能:
    1. 设置最大并发数
    2. 队列的暂停和继续
    3. 依赖关系

GCD

  1. ONCE 单例,代码只能执行一次
  2. after 延时
  3. 提供了非常多的底层功能!是NSOperation无法胜任的!

总结

GCD 是一个具备底层特性的框架,通过它,我们可以构建高层级的抽象行为。如果还有一些我没提到的可以用 GCD 构建的高层行为,请告诉我。

最后补上一张各种队列执行效果图:

17007340264698.jpg
17007340264698.jpg
17007340264717.jpg
17007340264717.jpg