一、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. Spark 基于物品的协同过滤算法实现

    J由于 Spark MLlib 中协同过滤算法只提供了基于模型的协同过滤算法,在网上也没有找到有很好的实现,所以尝试自己实现基于物品的协同过滤算法(使用余弦相似度距离) 算法介绍 基于物品的协同过滤算 ...

  2. 设置table的td宽度,不随文字变宽

    页面中table宽度设置width="600px"之后,宽度仍然不是固定的,文字太长后不换行,把table都撑变形了. 解决办法: table 设置 宽度,绝对宽度和相对都可以 t ...

  3. Mybatis-Generator插件的使用与Spring集成Mybatis的配置

    参考:http://blog.51cto.com/zero01/2103687 Mybatis-Generator是一个用于自动生成dao层接口.pojo以及mapper xml的一个Mybatis插 ...

  4. UML中的组合、聚合、关联、继承、实现、依赖

    转自:http://justsee.iteye.com/blog/808799 UML定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合. 继承 指的是一个类(称为子类.子接口)继承另外的一个类 ...

  5. 设计模式--适配器模式C++实现

    适配器模式C++实现 1定义Adapter 将一个类的接口变成客户端所需要的另外一种借口,从而使远不因为接口不匹配而无法合作的两个雷能够一起工作 又叫变压器模式,包装模式Wrapper 2类图 角色分 ...

  6. Gruntjs提高生产力(三)

    以下例子来自真实项目,有所删减 grunt-test project 目录结构如下 一我的目的: 1.在src-dev目录中开发最终产出于src目录 2.src-dev中的index目录相当于一个wi ...

  7. BZOJ 1003 [ZJOI2006]物流运输trans ★(Dijkstra + DP)

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=1003 思路 先Dijkstra暴力求出i..j天内不变换路线的最少花费,然后dp[i] = ...

  8. IOS-CocoaPods的详细安装与使用

    1.为什么需要CocoaPods 在进行iOS开发的时候,总免不了使用第三方的开源库,比如SBJson.AFNetworking.Reachability等等.使用这些库的时候通常需要: 下载开源库的 ...

  9. PHP---初探PHP

    初探PHP 虽然说前后端分离,但作为前端还是要跟数据打交道的,所以对后台语言的了解还是很有必要的.今天要学的就是PHP. 什么是PHP? PHP(外文名:PHP: Hypertext Preproce ...

  10. 转:kafka入门

    一.基本概念 介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计. 这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语:Kafk ...