ios多线程操作(六)—— GCD全局队列与主队列

GCD默认已经提供了全局的并发队列供整个应用使用,所以可以不用手动创建。

创建全局队列的函数为

dispatch_queue_t q = dispatch_get_global_queue(long identifier, unsigned long flags)

参数类型为:

long identifier:ios 8.0 告诉队列执行任务的“服务质量 quality of service”,系统提供的参数有:

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 之前
优先级

DISPATCH_QUEUE_PRIORITY_HIGH 2                
高优先级

DISPATCH_QUEUE_PRIORITY_DEFAULT 0             
默认优先级

DISPATCH_QUEUE_PRIORITY_LOW (-2)              
低优先级

     DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  后台优先级

BACKGROUND表示用户不需要知道任务什么时候完成,如果选择这个选项速度慢得令人发指,非常不利于调试!对于优先级推荐不要搞得太负责,就用最简单,以免发生优先级反转。

unsigned long flags:苹果官方文档是这样解释的: Flags that are reserved for future use。标记是为了未来使用保留的!所以这个参数应该永远指定为0

如果做ios8.0与ios7.0的适配,可以这样创建全局队列:

dispatch_queue_t q = dispatch_get_global_queue(0, 0);

试着用全局队列来做一下异步操作,看看是否为并发执行,如下代码

 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");

运行结果如下:

验证正确

现在我们来模拟一次操作,用户需要先登录之后才能执行两个下载操作,登录和下载都是个耗时操作,所以我们需要在后台开启一条子线程,根据现实情况两个下载操作需要并发执行,那如何实现该需要?借此,我们引出同步函数的作用!有如下代码

// 1. 队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);

    // 2. 任务
    void (^task)() = ^ {
        dispatch_sync(q, ^{
            NSLog(@"Login %@", [NSThread currentThread]);
        });
        dispatch_async(q, ^{
            NSLog(@"Download A %@", [NSThread currentThread]);
        });
        dispatch_async(q, ^{
            NSLog(@"Download B %@", [NSThread currentThread]);
        });
    };

    // 3. 异步执行 task
    dispatch_async(q, task);

执行结果如下:

再来一次:

结果无论如何都是在子线程上执行,而且登录永远都在最前面,至于哪条线程先下载我们不得而知,以上结果只是简单展示,如果开多下载基本书就可以展示更好的效果,这里就不演示了。

在MRC环境下,全局队列不需要释放内存。

当然,GCD本身自带了一种特殊的串行队列,所有放在主队列中的任务都会在主线程上执行。

程序一启动,主线程就已经存在,主队列也同时就存在了,所以主队列不需要创建,只需要获取,如下

 dispatch_queue_t q = dispatch_get_main_queue();

试着在主队列中执行异步任务:

dispatch_queue_t q = dispatch_get_main_queue();

    // 2. 异步执行
    for (int i = 0; i < 10; ++i) {
        dispatch_async(q, ^{
            NSLog(@"%@ - %d", [NSThread currentThread], i);
        });
    }
    NSLog(@"线程休眠1s");
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"come here - %@",[NSThread currentThread]);

执行的结果如下:

据此可得,主队列中,即使有异步任务,也会依次在主线程上执行,该例子中,主线程上的代码还未执行完,所以异步任务会等主线程上的任务执行完再执行。

那么如果在主线程上执行同步任务会如何呢?如下代码:

// 1.队列
    dispatch_queue_tq = dispatch_get_main_queue();
    NSLog(@"now I'm here");
    // 2. 同步执行
    dispatch_sync(q, ^{
        NSLog(@"%@", [NSThreadcurrentThread]);
    });
    NSLog(@"come here");

此时打印台打印出来的结果如下

程序只执行到第二句代码就无法执行下去了,为什么会这样呢?答案就是主线程被阻塞了,也就是死锁了!!!如果这时候屏幕上有与用户交互的UI,此时也会失去交互功能,像死机了一样!!!

我们都应该清楚,同步任务有一个特性,只要一添加到队列中就要马上执行,主队列中永远就只要一条线程——主线程,此时主线程在等待着主队列调度同步任务,而主队列发现主线程上还有任务未执行完,就不会让同步任务添加到主线程上,由此就造成了互相等待(主队列在等待主线程执行完已有的任务,而主线程又在等待主队列调度同步任务!),此时也就是所谓的死锁了!!!

那么如果有在主队列执行同步任务的需要呢?我们可以用一个异步任务包裹一个同步任务添加到主队列中!如下:

 // 全局队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);
    // 任务
    void (^task)() = ^ {
        NSLog(@"%@", [NSThread currentThread]);
       // 主队列上执行同步任务
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"come here %@", [NSThread currentThread]);
        });

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

    // 异步执行任务
    dispatch_async(q, task);
    NSLog(@"now i'm here - %@",[NSThread currentThread]);

执行结果如下:

主线程没有被阻塞!!!"now i‘m here“出现的位置不确定,但总会先于主队列中的同步函数!主队列的同步任务被添加到全局队列的异步任务中,全局队列会先让主线程上的任务先执行完再执行同步任务!

时间: 2024-08-02 06:55:24

ios多线程操作(六)—— GCD全局队列与主队列的相关文章

iOS 多线程:『GCD』详尽总结

本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法.这大概是史上最详细.清晰的关于 GCD 的详细讲解+总结的文章了.通过本文,您将了解到: 1. GCD 简介 2. GCD 任务和队列 3. GCD 的使用步骤 4. GCD 的基本使用(6种不同组合区别) 5. GCD 线程间的通信 6. GCD 的其他方法(栅栏方法:dispatch_barrier_async.延时执行方法:dispatch_after.一次性代码(只执行一次):dispatch_once.快速迭代方法:dis

iOS多线程开发之GCD(下篇)

上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题.有兴趣的朋友可以回顾<iOS多线程开发之GCD(上篇)>和<iOS多线程开发之GCD(中篇)>. 言归正传,我们首先来回顾下死锁,所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源(如数据源,内存等,变量不是资源)而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去. 死锁形成的原因: 系统资源不足 进程(线程)推进的顺序不恰当: 资源分配不当 死锁形成的条件:

IOS多线程开发之GCD

概要 GCD的全称是Grand Central Dispatch(译为中心调度队列?),可以理解为线程管理队列,是苹果公司为多核的并行运算提出的解决方案,能够根据系统环境自适应线程管理,基本属于全自动的线程管理. 在GCD里面,任务需要放到队列里面执行,队列根据自身属性分发任务执行,不过原则总是FIFO.队列分为串行和并行队列,串行队列是队列里面只有一个线程,所以队列里面只有一个任务在执行,而并行则会根据系统环境,自动调节线程数,可支持同时多个任务执行. GCD提供了创建以及获取队列的方法,包括

ios多线程操作(五)—— GCD串行队列与并发队列

GCD的队列可以分为2大类型,分别为串行队列和并发队列 串行队列(Serial Dispatch Queue): 一次只调度一个任务,队列中的任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务) 创建一个队列 dispatch_queue_t q = dispatch_queue_create(const char *label, dispatch_queue_attr_t attr) 参数: const char *label:队列的名称 dispatch_queue_attr_t

iOS 多线程知识总结 GCD基础知识

进程的基本概念: 1.每一个进程都是一个一个应用程序,都有独立的内存空间,一般来说一个应用程序存在一个进程存在一个进程,但也有多个进程的情况. 2.同一个进程中的线程共享内存中内存中资源. 多线程的基本概念: 1.每一个程序都有一个主线程,程序启动时创建(调用main函数来启动) 2.主线程的生命周期是和其他应用程序绑定的,程序退出时,主线程也就停止了. 3.多线程技术表示,一个应用程序有多个线程,使用多线程能提高CPU的使用效率,防止线程阻塞 4.任何有可能阻塞主线程的任务不要在主线程中执行(

iOS 多线程学习笔记 —— GCD

本文复制.参考自文章:iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://blog.csdn.net/totogo2010/原创,欢迎转载分享.请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢! 这里对原作者的辛勤工作表示感谢! 1. 简介 GCD (Grand Central Dispatch) 是建立任务并行执行的线程池模式的基础上的,以优化支持多核.多处理器系统

GCD全局队列与主队列

GCD默认已经提供了全局的并发队列供整个应用使用,所以可以不用手动创建. 创建全局队列的函数为 dispatch_queue_t q = dispatch_get_global_queue(long identifier, unsigned long flags) 参数类型为: long identifier:ios 8.0 告诉队列执行任务的“服务质量 quality of service”,系统提供的参数有: QOS_CLASS_USER_INTERACTIVE 0x21,         

iOS多线程开发之GCD 用法入门

我们知道,在iOS中进行多线程编程,主要有三种方式:[NSThread].[NSOperation]和[GCD].其中又以[GCD]为苹果官方最为推荐.本文将利用一个简单的demo,简述GCD的用法入门,以及本人对GCD的一点肤浅理解和学习心得. 先把参考文章列出: http://www.cnblogs.com/kenshincui/p/3983982.html http://www.cnblogs.com/sunfrog/p/3305614.html http://mobile.51cto.c

iOS多线程编程之GCD

1.GCD介绍 Grand Central Dispatch 简称(GCD)是Apple公司开发的技术,相比NSThread或NSOperation使用方便,并且优点是当处理器为多核时能利用多核的特征来创建线程.它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用. 2.GCD分类 GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行,dispatch queue分为下面3种:一种是串行队列(Serial Dispatch Queue),一种是并行