zoukankan      html  css  js  c++  java
  • step 4 GCD 队列演练

    串行队列

    特点

    • 以先进先出的方式,顺序调度队列中的任务执行
    • 无论队列中所指定的执行任务函数是同步还是异步,都会等待前一个任务执行完成后,再调度后面的任务

    队列创建

    dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);

     

    dispatch_queue_t queue = dispatch_queue_create("queueName", NULL);

    串行队列演练

    1 串行队列 同步执行

    /**

     提问:是否开线程?是否顺序执行?come here 的位置?

     */

    - (void)gcdDemo1 {

        // 1. 队列

        dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);

     

        // 2. 执行任务

        for (int i = 0; i < 10; ++i) {

            NSLog(@"--- %d", i);

     

            dispatch_sync(q, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

        }

     

        NSLog(@"come here");

    }

    • 串行队列 异步执行

    /**

     提问:是否开线程?是否顺序执行?come here 的位置?

     */

    - (void)gcdDemo2 {

        // 1. 队列

        dispatch_queue_t q = dispatch_queue_create("foo", NULL);

     

        // 2. 执行任务

        for (int i = 0; i < 10; ++i) {

            NSLog(@"--- %@ %d", [NSThread currentThread], i);

     

            dispatch_async(q, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

        }

     

        NSLog(@"come here");

    }

     

    并发队列

    特点

    • 以先进先出的方式,并发调度队列中的任务执行
    • 如果当前调度的任务是同步执行的,会等待任务执行完成后,再调度后续的任务
    • 如果当前调度的任务是异步执行的,同时底层线程池有可用的线程资源,会再新的线程调度后续任务的执行

    队列创建

    dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

    并发队列演练

    • 并发队列 异步执行

    /**

     提问:是否开线程?是否顺序执行?come here 的位置?

     */

    - (void)gcdDemo3 {

     

        // 1. 队列

        dispatch_queue_t q = dispatch_queue_create("foo", DISPATCH_QUEUE_CONCURRENT);

     

        // 2. 执行任务

        for (int i = 0; i < 10; ++i) {

            dispatch_async(q, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

        }

     

        NSLog(@"come here");

    }

    • 并发队列 同步执行

    /**

     提问:是否开线程?是否顺序执行?come here 的位置?

     */

    - (void)gcdDemo4 {

     

        // 1. 队列

        dispatch_queue_t q = dispatch_queue_create("foo", DISPATCH_QUEUE_CONCURRENT);

     

        // 2. 执行任务

        for (int i = 0; i < 10; ++i) {

            dispatch_sync(q, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

            NSLog(@"---> %i", i);

        }

     

        NSLog(@"come here");

    }

    主队列

    特点

    • 专门用来在主线程上调度任务的队列
    • 不会开启线程
    • 以先进先出的方式,在主线程空闲时才会调度队列中的任务在主线程执行
    • 如果当前主线程正在有任务执行,那么无论主队列中当前被添加了什么任务,都不会被调度

    队列获取

    • 主队列是负责在主线程调度任务的
    • 会随着程序启动一起创建
    • 主队列只需要获取不用创建

    dispatch_queue_t queue = dispatch_get_main_queue();

    主队列演练

    • 主队列,异步执行

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

        [self gcdDemo1];

     

        [NSThread sleepForTimeInterval:1];

        NSLog(@"over");

    }

     

    - (void)gcdDemo1 {

     

        dispatch_queue_t queue = dispatch_get_main_queue();

     

        for (int i = 0; i < 10; ++i) {

            dispatch_async(queue, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

            NSLog(@"---> %d", i);

        }

     

        NSLog(@"come here");

    }

    在主线程空闲时才会调度队列中的任务在主线程执行

    • 主队列,同步执行

    // MARK: 主队列,同步任务

    - (void)gcdDemo6 {

        // 1. 队列

        dispatch_queue_t q = dispatch_get_main_queue();

     

        NSLog(@"!!!");

     

        // 2. 同步

        dispatch_sync(q, ^{

            NSLog(@"%@", [NSThread currentThread]);

        });

     

        NSLog(@"come here");

    }

    主队列和主线程相互等待会造成死锁

    同步任务的作用

    同步任务,可以让其他异步执行的任务,依赖某一个同步任务

    例如:在用户登录之后,再异步下载文件!

    - (void)gcdDemo1 {

        dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

     

        dispatch_sync(queue, ^{

            NSLog(@"登录 %@", [NSThread currentThread]);

        });

     

        dispatch_async(queue, ^{

            NSLog(@"下载 A %@", [NSThread currentThread]);

        });

     

        dispatch_async(queue, ^{

            NSLog(@"下载 B %@", [NSThread currentThread]);

        });

    }

    • 代码改造,让登录也在异步执行

    - (void)gcdDemo2 {

        dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

     

        void (^task)() = ^{

            dispatch_sync(queue, ^{

                NSLog(@"登录 %@", [NSThread currentThread]);

            });

     

            dispatch_async(queue, ^{

                NSLog(@"下载 A %@", [NSThread currentThread]);

            });

     

            dispatch_async(queue, ^{

                NSLog(@"下载 B %@", [NSThread currentThread]);

            });

        };

     

        dispatch_async(queue, task);

    }

    1  主队列调度同步队列不死锁

    - (void)gcdDemo3 {

     

        dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

     

        void (^task)() = ^ {

            dispatch_sync(dispatch_get_main_queue(), ^{

                NSLog(@"死?");

            });

        };

     

        dispatch_async(queue, task);

    }

    主队列在主线程空闲时才会调度队列中的任务在主线程执行

    全局队列

    • 是系统为了方便程序员开发提供的,其工作表现与并发队列一致

    全局队列 & 并发队列的区别

    1  全局队列

    ◦                     没有名称

    ◦                     无论 MRC & ARC 都不需要考虑释放

    ◦                     日常开发中,建议使用"全局队列"

    2  并发队列

    ◦                     有名字,和 NSThread 的 name 属性作用类似

    ◦                     如果在 MRC 开发时,需要使用 dispatch_release(q); 释放相应的对象

    ◦                     dispatch_barrier 必须使用自定义的并发队列

    ◦                     开发第三方框架时,建议使用并发队列

    全局队列异步任务

    /**

     提问:是否开线程?是否顺序执行?come here 的位置?

     */

    - (void)gcdDemo8 {

        // 1. 队列

        dispatch_queue_t q = dispatch_get_global_queue(0, 0);

     

        // 2. 执行任务

        for (int i = 0; i < 10; ++i) {

            dispatch_async(q, ^{

                NSLog(@"%@ - %d", [NSThread currentThread], i);

            });

        }

     

        NSLog(@"come here");

    }

    运行效果与并发队列相同

    参数

    • 服务质量(队列对任务调度的优先级)/iOS 7.0 之前,是优先级

                            iOS 8.0(新增,暂时不能用,今年年底)

                                              QOS_CLASS_USER_INTERACTIVE 0x21, 用户交互(希望最快完成-不能用太耗时的操作)

                                              QOS_CLASS_USER_INITIATED 0x19, 用户期望(希望快,也不能太耗时)

                                              QOS_CLASS_DEFAULT 0x15, 默认(用来底层重置队列使用的,不是给程序员用的)

                                              QOS_CLASS_UTILITY 0x11, 实用工具(专门用来处理耗时操作!)

                                              QOS_CLASS_BACKGROUND 0x09, 后台

                                              QOS_CLASS_UNSPECIFIED 0x00, 未指定,可以和iOS 7.0 适配

                            iOS 7.0

                                              DISPATCH_QUEUE_PRIORITY_HIGH 2 高优先级

                                              DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认优先级

                                              DISPATCH_QUEUE_PRIORITY_LOW (-2) 低优先级

                                              DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台优先级

    • 为未来保留使用的,应该永远传入0

    结论:如果要适配 iOS 7.0 & 8.0,使用以下代码: dispatch_get_global_queue(0, 0);

    最怕你一生碌碌无为 还安慰自己平凡可贵
  • 相关阅读:
    [VC++入门]C++中常用的运算符及微软自定义类型
    搜索引擎蜘蛛爬虫原理
    Enterprise Library 5.0
    Installshield 12 中文系列教程之 定义安装必要条件
    installshield脚本
    c# 事物处理
    InStallShield网络资源参考
    Could not execute query against OLE DB provider 'OraOLEDB.Oracle'
    frameset小结
    最痛心的距离
  • 原文地址:https://www.cnblogs.com/fakeCoder/p/5093671.html
Copyright © 2011-2022 走看看