一、GCD介绍
1.what is GCD?
Grand Central Dispatch 中枢调度器。用很简单的方式实现了极为复杂繁琐的多线程编程。异步执行任务的技术之一。
 
2.GCD存在于libdispatch.dylib库中。默认加载了这个库,在程序运行过程中会动态的加载这个库,不需手动导入。
 
3.开发者要做的只是定义想执行的任务并追加到适当的队列中。(1.定制任务(BLock代码块) 2.放到适当的队列中(Dispatch queue))。
 
4.相关术语解释
同步(Synchronous)、异步(Asynchronous)、并发(concurrent)、并行(Parallelism)、串行(Serial):
 
同步vs异步:描述当一个函数相对于任务完成。同步需要等任务完成后才返回;异步不需要等任务完成就返回。
串行vs并发:描述当前任务相对于其它任务被执行。任务串行执行就是每次只有一个任务被执行,任务并发执行就是在同一时间可以有多个任务被执行。
并发vs并行:都是同时处理多个任务的概念。并行指多个任务在同一时刻发生;并发指多个任务在同一时间间隔内发生。
并发:在操作系统中,并发是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
 
上下文切换(Context Switch):一个上下文切换指当你在单个进程里切换执行不同的线程时存储与恢复执行状态的过程。
 
二、队列
1.概念:
1)串行队列(Serial Dispatch Queue):让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
2)并发队列(Concurrent Dispatch Queue):可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)并发功能只有在异步(dispatch_async)函数下才有效
???程序运行时,线程和进程,开多个线程,程序运行的生命周期
 
2.创建队列
1.通过dispatch_queue_create
第一个参数:队列的名字
第二个参数:队列的类型(NULL或Serial为串行队列,concurrent为并发队列)
dispatch_queue_t myQueue =
                 dispatch_queue_create("com.wq.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue =
                 dispatch_queue_create("com.wq.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
 
3.获取系统提供的
1)Main Dispatch Queue 主线程中执行,串行队列。
   dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
   
2)Global Dispatch Queue 并发队列。
dispatch_queue_t globalDispatchQueue =           
                 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
第一个参数:优先级(高->默认->低->后台)
第二个参数:留以后用的,暂时不用,设为0
 
3.队列知识点
 
三、一些方法
    //串行队列
    dispatch_queue_t queueSerial = dispatch_queue_create("jr", DISPATCH_QUEUE_SERIAL);
 
    //并行队列

dispatch_queue_t queueConcu = dispatch_queue_create("jr2", DISPATCH_QUEUE_CONCURRENT);

//1、循环多次使用

//(1)添加串行队列,同步执行。可以当for循环使用(在主线程中)

 
    dispatch_apply(3, queueSerial, ^(size_t t) {// 参数^(size_t),需要自己加一个^(size_t t),否则有问题
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%@", [NSThread currentThread]);
 
    });

//(2)添加并行队列,同步执行。可以当for循环使用(如果循环次数大于1,则开子线程)

 
    dispatch_apply(3, queueConcu, ^(size_t t) {// 参数^(size_t),需要自己加一个^(size_t t),否则有问题
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%@", [NSThread currentThread]);
 
    });
   

//(3)参数size_t的作用:打印的是0.1.2.3.。。的序号

 
    dispatch_apply(3, queueSerial, ^(size_t t) {
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%li == %@", t, [NSThread currentThread]);
 
    });   

//(4)以上都是在主线程中进行的。如果想在子线程中执行,需要这样做

 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 
        dispatch_apply(3, queueConcu, ^(size_t t) {
 
            [NSThread sleepForTimeInterval:1];
 
            NSLog(@"%li == %@", t, [NSThread currentThread]);
 
        });
 
    });
 

//2、分组(可以监听组内子线程是否全部都执行完成)

    dispatch_group_t group = dispatch_group_create();   
 
    dispatch_group_async(group, queueConcu, ^{
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%@", [NSThread currentThread]);
 
    });
 
    dispatch_group_async(group, queueConcu, ^{
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%@", [NSThread currentThread]);
 
    });
 
    dispatch_group_async(group, queueConcu, ^{
 
        [NSThread sleepForTimeInterval:1];
 
        NSLog(@"%@", [NSThread currentThread]);
 
    });
   
    dispatch_group_notify(group, queueConcu, ^{
 
        NSLog(@"----%@", [NSThread currentThread]);
 
    });
 
 

//3、延迟(写在这个块中的代码都是在主线程中执行的)

 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

[NSThread sleepForTimeInterval:2];

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

});

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

    timer = [NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(touchesBegan) userInfo:nil repeats:YES];
   

//4.设置障碍(在同一队列中,只要添加了障碍,不管有没有创建多线程,他后边的任务都要跨国这个障碍,即等待这个障碍结束)

 
    dispatch_async(queueConcu, ^{
 
        NSLog(@"11111");
 
    });
   
    dispatch_barrier_async(queueConcu, ^{
 
        [NSThread sleepForTimeInterval:5];
 
    });
   
    dispatch_async(queueConcu, ^{
 
         NSLog(@"11111");
 
    });
 
    dispatch_async(queueConcu, ^{
 
        NSLog(@"11111");
 
    });
    
    

//5、让代码只执行一次

 
    static dispatch_once_t oneToken;
 
    dispatch_once(&oneToken, ^{
 
        NSLog(@"=======");
 
    });
 
四、注意事项
 
1.dispatchbarrier\(a)sync只在自己创建的并发队列上有效,在全局(Global)并发队列、串行队列上,效果跟dispatch_(a)sync效果一样。既然在串行队列上跟dispatch_(a)sync效果一样,那就要小心别死锁!
 
2.dispatch_after只是延时提交block,并不是延时后立即执行。
 
3.dispatch_suspend,dispatch_resume提供了“挂起、恢复”队列的功能,简单来说,就是可以暂停、恢复队列上的任务。但是这里的“挂起”,并不能保证可以立即停止队列上正在运行的block。
 
4.dispatch_apply的作用是在一个队列(串行或并行)上“运行”多次block,其实就是简化了用循环去向队列依次添加block任务。dispatch_apply会“等待”其所有的循环运行完毕才往下执行。
//创建异步串行队列
dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_CONCURRENT);
//运行block3次
dispatch_apply(3, queue, ^(size_t i) {
    NSLog(@"apply loop: %zu", i);
});
//打印信息
NSLog(@"After apply");
 
明明是提交到并发队列去运行,但是“After apply”居然在apply loop:0/1/2后打印,也就是说,dispatch_apply将外面的线程(main线程)“阻塞”了!
 
4.dispatch_sync导致的死锁。//在main线程使用“同步”方法提交Block,必定会死锁
5.一定要避免dispatch_apply的嵌套调用。会导致死锁。
dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);
        
dispatch_apply(3, queue, ^(size_t i) {
NSLog(@"apply loop: %zu", i);
    
    //再来一个dispatch_apply!死锁!      
dispatch_apply(3, queue, ^(size_t j) {
NSLog(@"apply loop inside %zu", j);
});
});

GCD基础的更多相关文章

  1. iOS 开发之 GCD 基础

    header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...

  2. iOS开发之GCD基础

    重新回顾.学习GCD.Block.先贴出一篇不错的讲解GCD基础使用的文章 原文地址:http://blog.csdn.net/aolan1108/article/details/17283415 做 ...

  3. GCD基础知识总结

    iOS三种多线程编程技术: 1.NSThread 2.NSOperation 3.GCD(Grand Central Dispatch) 从上到下,抽象度层次从低到高,抽象度越高的使用越简单,也是Ap ...

  4. 多线程基础(六)GCD基础

    更多值得学习的GCD知识,可以学习: Grand Central Dispatch (GCD) Reference GCDObjC 1.GCD的基本概念     什么是GCD 全称是Grand Cen ...

  5. iOS GCD基础篇 - 同步、异步,并发、并行的理解

    1.关于GCD - GCD全称是Grand Central Dispatch  - GCD是苹果公司为多核的并行运算提出的解决方案  - GCD会自动利用更多的CPU内核(比如双核.四核)  - GC ...

  6. GCD基础知识

    并行和并发 在英文世界里,「并行」和「并发」的区别比较清晰,「并行」对应parallelism,「并发」对应concurrency:但在中文世界里二者仅一字之差,两个概念非常容易弄混淆: 各种资料对「 ...

  7. IOS GCD定时器

    提到定时器,NStimer肯定是我们最为熟悉的. 但是NStimer有着很大的缺点,并不准确. 通俗点说,就是它该做他的事了,但是由于其他事件的影响,Nstimer会放弃他应该做的. 而GCD定时器, ...

  8. iOS GCD中级篇 - dispatch_group

    1.关于dispatch_group 把一组任务提交到队列中,这些队列可以不相关,然后监听这组任务完成的事件. 最常见的几个方法: 1.dispatch_group_create创建一个调度任务组 2 ...

  9. [BZOJ 2257][JSOI2009]瓶子和燃料 题解(GCD)

    [BZOJ 2257][JSOI2009]瓶子和燃料 Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子 ...

随机推荐

  1. 防止xss(脚本攻击)的方法之过滤器

    一  什么是脚本注入 概念我就不说了 直接百度一份 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代码和客户端 ...

  2. ubuntu16.04后续工作

    一.ruijie https://blog.csdn.net/u012217085/article/details/24369335 https://blog.csdn.net/Lv_Victor/a ...

  3. 解题报告:poj2387 dijkstra

    2017-09-17 17:37:03 writer:pprp dijkstra模板题目,注意去重 代码如下: /* @theme:poj 2387 @declare:最短路,从N到1点 @write ...

  4. Python学习札记(十八) 高级特性4 生成器

    参考:生成器 Note 1.通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的,且容易造成空间浪费.所以,如果列表元素可以按照某种算法推算出来,那我们可以在循环的过程中 ...

  5. C#:手把手教你用C#打包应用程序(安装程序卸载程序)

    摘要:本文介绍在C#中手把手教你用C#打包应用程序(安装程序卸载程序) 1:新建安装部署项目 打开VS,点击新建项目,选择:其他项目类型->安装与部署->安装向导(安装项目也一样),然后点 ...

  6. javascript 关于节点

    重复使用对像可以用 var a,b; with(document){ a = getElementById('aID') b = getElementById('bID') } 关于节点访问: par ...

  7. 对dataframe中某一列进行计数

    本来是一项很简单的任务...但很容易忘记搞混..所以还是记录一下 方法一: df['col'].value_counts() 方法二: groups = df.groupby('col') group ...

  8. class文件直接修改_反编译修改class文件变量

    今天笔者同事遇到一个问题,客户同事的数据库连接信息直接写在代码中,连接的密码改了,但是又没有源代码,所以只能直接修改Java class文件. 记录一下修改步骤: 1.下载JClassLib_wind ...

  9. Huffuman Coding (哈夫曼编码)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头 ...

  10. IntelliJ IDEA 返回上次编辑(鼠标停留)的地方

    idea默认的是 : Ctrl + Alt + 左箭头,与笔记本的 旋转屏幕冲突: 找到: 我更改成了: Ctrl + CapsLock :暂时没发现冲突.