********************************* 基本概念 ***********************************

1. Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法,是苹果主推的多线程处理机制。在多核CPU的状态下,GCD的性能很高。

它自动利用更多的CPU内核,管理线程生命周期,程序员不需要编写任何线程管理代码,只需要给定要让GCD执行的任务。

2. GCD是纯C语言的,GCD中的函数大多数以dispatch开头。

3. GCD存在于 libdispatch.dylib 库中,但不需要手动导入,默认包含。

4. GCD的两个核心概念:任务队列

将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行,遵行FIFO原则:先进先出,后进后出。

5. GCD一般和Block一起使用,在Block回调中处理程序操作。

****************************** GCD的三种调度队列 ******************************

首先需要明确4个术语的概念:

1. 异步(async):在另一条线路中执行,具备开启新线程的能力

2. 同步(sync):在当前线路执行,不具备开启新线程的能力

3. 并行(concurrent):自动开启多个线程让多个任务同时执行,并行功能只在异步条件下才有效

4. 串行(serial):一个任务执行完成才执行下一个

总而言之:同步和异步决定要不要开启新的线程,并行和串行决定任务执行的方式。

GCD的三种调度队列:

1. 运行在主线程的主队列Main queue,一般是执行和UI相关的任务比如更新UI的显示,通过dispatch_get_main_queue获取。

2. 并发队列global dispatch queue,一般是后台长时间执行的任务比如下载,默认提供,不需要创建,通过dispatch_get_global_queue获取。

 dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags)
 // dislatch_queue_t 表示返回的是一个队列
 /* 第一个参数dispatch_queue_priority_t priority表示优先级,后面会使用默认优先级
 DISPATCH_QUEUE_PRIORITY_DEFAULT */
 // 第二个参数unsigned long flags是以后才会使用的,所以先传0

 // 用法
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
 // 获得全局并发队列queue

3. 串行队列serial queues,获得串行有两种途径

1) 使用dispatch_queue_create函数创建串行队列

 dispatch_queue_t  dispatch_queue_create(const char *label,  dispatch_queue_attr_t attr)
 // 第一个参数是队列名称,第二个参数是队列属性,一般传NULL

 // 用法
 dispatch_queue_t queue = dispatch_queue_create("blahblahblah",  NULL);

 //非ARC需要手动释放队列
 //dispatch_release(queue);

2) 使用主队列(一种特殊的串行队列,GCD自带的在主线程中执行的队列)

 dispatch_get_main_queue()

 // 用法
 dispatch_queue_t queue = dispatch_get_main_queue();

********************************* 代码示例 **********************************

1. 用异步函数向并发队列添加任务

// ViewController.m

#import <ViewController.h>

@interface ViewController()

@end

@implementation ViewController
-(void)viewDidLoad{
    [super viewDidLoad];
    //1. 获得全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,);
    //2. 添加任务到队列中
    dispatch_async(queue,^{
        NSLog(@"下载图片1----%@",[NSThread currentThread]);
    });
    dispatch_async(queue,^{
        NSLog(@"下载图片2----%@",[NSThread currentThread]);
    });
    dispatch_async(queue,^{
        NSLog(@"下载图片3----%@",[NSThread currentThread]);
    });
    NSLog(@"主线程----%@",[NSThread mainThread]);

}
@end

// 异步,并发,开启了3个子线程

2. 用异步函数向串行队列添加任务

// ViewController.m

#import <ViewController.h>

@interface ViewController()

@end

@implementation ViewController
-(void)viewDidLoad{    [super viewDidLoad];
    NSLog(@"主线程----%@",[NSThread mainThread]);
    dispatch_queue_t queue = diapatch_queue_create("BlahBlahBlah",NULL);
    dispatch_async(queue,^{
        NSLog(@"下载图片1----%@",[NSThread currentThread])
    });
    dispatch_async(queue,^{
        NSLog("下载图片2----%@",[NSThread currentThread]);
    })
    diapatch_async(queue,^{
        NSLog("下载图片3----%@",[NSThread currentThread]);
    })

    // 释放队列
    // dispatch_release(queue);
)

// 异步,串行,只开启一条子线程,子线程的任务串行执行

3. 用同步函数向并发队列添加任务

 // ViewController.m

 #import <ViewController.h>

 @interface ViewController()

 @end

 @implementation ViewController
 -(void)viewDidLoad{
     [super viewDidLoad];
     NSLog(@"主线程----%@",[NSThread mainThread]);
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,);
     dispatch_sync(queue,^{
         NSLog("下载图片1----%@",[NSThread currentThread]);
     })
     dispatch_sync(queue,^{
         NSLog("下载图片2----%@",[NSThread currentThread]);
     })
     dispatch_sync(queue,^{
         NSLog("下载图片3----%@",[NSThread currentThread]);
     })

 )

 //  同步,并发,并发队列失去并发功能,不具备开启新线程的能力,只有主线程

4. 用同步函数向串行队列添加任务

 // ViewController.m

 #import <ViewController.h>

 @interface ViewController()

 @end

 @implementation ViewController
 -(void)viewDidLoad{
     [super viewDidLoad];
     NSLog(@"主线程----%@",[NSThread mainThread]);
     dispatch_queue_t queue = dispatch_queue_create("blahblahblah",NULL);
     dispatch_sync(queue,^{
         NSLog(@"下载图片1----%@",[NSThrea currentThread]);
     })
     dispatch_sync(queue,^{
         NSLog(@"下载图片2----%@",[NSThrea currentThread]);
     })
     dispatch_sync(queue,^{
         NSLog(@"下载图片3----%@",[NSThrea currentThread]);
     })

 )
 @end

 // 同步,串行,没有开启新线程的能力,只有主线程

总结:

同步函数

(1)并发队列:不会开线程

(2)串行队列:不会开线程

异步函数

(1)并发队列:能开启N条线程

(2)串行队列:开启1条线程

********************************线程死锁***********************************

不能使用同步函数向主线程添加任务:

 dispatch_sync(diapatch_get_main_queue(),^{
     NSLog("线程死锁");
 })

在程序中写这样的语句不会有任何输出。

理解关键是:dispatch_sync 函数要到block里的内容执行完才能返回,主线程要等待函数返回。

dispatch_async 函数一被调用,马上返回,因此主线程得到返回就可以去做别的事。

原因在于:主线程调用同步函数dispatch_sync,添加任务到主队列(属于串行队列),主线程等待函数的返回,函数等待主线程结束才能执行block的内容,而同步函数必须等到执行完内部内容才能返回,因此造成线程死锁。

就像:A等待B买回来的材料才知道该干嘛,而B需要A提供自己要做什么的信息来决定买什么材料。

因此要向主队列中添加任务,用异步函数。

 dispatch_async(dispatch_get_main_queue,^{
     NSLog(@"不会造成线程死锁");
 })

****************************持续更新中****************************

多线程-GCD学习笔记的更多相关文章

  1. Java多线程技术学习笔记(二)

    目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...

  2. 多线程编程学习笔记——async和await(一)

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

  3. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

  4. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  5. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  6. 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端

    接上文 多线程编程学习笔记——使用异步IO 二.   编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...

  7. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  8. 多线程编程学习笔记——使用异步IO

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  9. Java多线程技术学习笔记(一)

    目录: 概述 多线程的好处与弊端 JVM中的多线程解析 多线程的创建方式之一:继承Thread类 线程的状态 多线程创建的方式之二:实现Runnable接口 使用方式二创建多线程的好处 多线程示例 线 ...

随机推荐

  1. [置顶] RGB颜色查询对照表

    因为兼容性问题,色阶板功能只能在IE浏览器中运行 RGB颜色对照表   #FFFFFF   #FFFFF0   #FFFFE0   #FFFF00   #FFFAFA   #FFFAF0   #FFF ...

  2. [C#] 常用工具类——直接在浏览器输出数据

    /// <summary> /// <para> </para> /// 常用工具类——直接在浏览器输出数据 /// <para> ---------- ...

  3. SQL基础之 时间戳

    本文转载:http://www.cnblogs.com/liuhh/archive/2011/05/14/2046544.html 一直对时间戳这个概念比较模糊,相信有很多朋友也都会误认为:时间戳是一 ...

  4. c#判断输入textbox是否为数字

    asp.net判断输入文字是否是数字 方案一:/**//// <summary> /// 名称:IsNumberic /// 功能:判断输入的是否是数字 /// 参数:string oTe ...

  5. C#通过FTP账号上传、修改、删除文件 FTPClient

    下面类文件中,主要做的工作是:从ftp服务器上下载文件把本地文件替换.添加.或删除功能,在替换本地文件时会先备份一下本地的文件,若整个操作都完成了就会发出commit命令,表示全部替换成功.若中间操作 ...

  6. mybatis11 sqlMapConfig.xml文件说明

    1sqlMapConfig.xml SqlMapConfig.xml中配置的内容和顺序如下: properties(属性) settings(全局配置参数) typeAliases(类型别名) typ ...

  7. spring注解:@PostConstruct和@PreDestroy

    关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种: 第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 第二 ...

  8. 【Android】Intent的使用-返回数据给上一个活动

    第一个Activity  A启动另外一个Activity B,B返回数据给A ============================================================= ...

  9. CentOS6.5编译安装最新MySQL 5.7.11

    安装前工作:1,从官方网址下载MySQL5.7.11源码包,大概49M2,安装好CentOS6.5 64位操作系统.建议update操作系统,以便是此版本最新的3. yum -y install  g ...

  10. Linux网络相关命令小结

    # ifconfig # ifup/ifdown # route -n # ip link show //显示本机所有接口信息 # traceroute # netstat //查看本机网络连接与后门 ...