一、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. pyspider—爬取视频链接

    #!/usr/bin/env python # -*- encoding: utf-8 -*- # Created on 2015-03-20 09:46:20 # Project: fly_spid ...

  2. saga+.net core 分布式事务处理

    Apache ServiceComb Saga 是一个微服务应用的数据最终一致性解决方案 中文官方地址:https://github.com/apache/servicecomb-saga/blob/ ...

  3. Elasticsearch Head 集群健康值:未连接

    安装elasticsearch 6.0  x-pack后,登录9200端口需要用户和密码, 这样,在使用elasticsearch head时,就不能直接访问9100了. 按照官方文档的要求,http ...

  4. 【Python】学习笔记之列表生成式

    列表生成式 主要用于生成较为复杂的列表 常用用法 >>> [x * x for x in range(5) if x % 3 !=1 ] [0, 4, 9] #返回除以3余数不为1的 ...

  5. mysql的基本的数据库的查询

    学习一个数据库我们要学习哪些东西: sql数据库的话, curd. 对于查询,要注意表的关联的查询. 索引,触发器,对于控制连接量,脚本, 数据库的可视化工具,权限管理. http://www.360 ...

  6. R-模式(mode)和类(class)

    数据模式:mode函数显示任何对象的模式.常见的单个的对象模式是逻辑型(Logical).数值型(Numeric).字符型(Character). 常用到的数据模式是列表(list). 逻辑型:TRU ...

  7. 场景设计以及Manual Scenario和Goal-OrientedScenario的区别

    Manual Scenario 手工场景 主要是设计用户变化,通过手工场景可以帮助我们分析系统的性能瓶颈.手动方案:如果要生成手动方案,请选择此方法.通过创建组并指定脚本.负载生成器和每组中包括的 V ...

  8. python脚本6_打印菱形

    #输入菱形最宽的行所在的行数,打印菱形 m = int(input(">>>")) for n in range(m): print(" "* ...

  9. Android6.0------权限申请管理(单个权限和多个权限申请)

    Android开发时,到6.0系统上之后,有的权限就得申请才能用了. Android将权限分为正常权限 和 危险权限 Android系统权限分为几个保护级别.需要了解的两个最重要保护级别是 正常权限  ...

  10. fio测试freenas共享的iscsi磁盘性能

    4k随机读iops: fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=randread -filename=/dev/sdb -iodepth=32 ...