一、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. mybatis中的映射类型

  2. LeetCode——remove-duplicates-from-sorted-list-ii

    Question Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only dist ...

  3. POJ2159 ancient cipher - 思维题

    2017-08-31 20:11:39 writer:pprp 一开始说好这个是个水题,就按照水题的想法来看,唉~ 最后还是懵逼了,感觉太复杂了,一开始想要排序两串字符,然后移动之类的,但是看了看 好 ...

  4. apollo 部门管理

    apollo 默认部门有两个.如果想要增加自己的部门,只能通过数据库ApolloPortalDB 修改表ServiceConfig中organizations即可:

  5. SPSS t 检验

    在针对连续变量的统计推断方法中,最常用的是 t 检验和方差分析两种. t 检验,又称 student t 检验,主要用于样本含量较小(例如n<30),总体标准差未知的正态分布资料.它是用 t 分 ...

  6. jsplumb 的初次使用

    最近的项目要能创建流程, 流程配置什么的就找了 jsplumb 来做流程的显示配置.经过两天的研究成果已经很明显了 参考了以下一些大神们的博客: jsplumb 中文教程 连线绘图工具库介绍 附简单在 ...

  7. iPhone 和Android应用,特殊的链接:打电话,短信,email

    下面的这篇文章主要是说,网页中的链接如何写,可以激活电话的功能. 例如,页面中展示的是一个电话号码,当用户在手机浏览器里面点击这个电话号码的时候,手机会弹出拨号的面板,或者是短信程序会启动等. 1. ...

  8. Codeforces Round #349 (Div. 2)

    第一题直接算就行了为了追求手速忘了输出yes导致wa了一发... 第二题技巧题,直接sort,然后把最大的和其他的相减就是构成一条直线,为了满足条件就+1 #include<map> #i ...

  9. ansible modules开发(二)

    四 使用其他语言发开module cd /etc/ansible cat library/touch.sh #!/bin/sh args_file=$1 [ ! -f "$args_file ...

  10. 验证email是否合法

    https://buluo.qq.com/p/detail.html?bid=339910&pid=6675390-1514450689&from=grp_sub_obj 场景1:验证 ...