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

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. phpstorm 解决svn 无法提交的问题

    phpstorm 无法用svn 提交 提示如下错误: 网上找的解决办法 : 由于安装的TortoiseSVN工具,本身是带有command-line功能的(没有安装)如图: 使用Intellij ID ...

  2. 基于前端javascript的搜索功能

    发表于 2013/11/07 当在数据量不是很大,而且没有后端对应的功能接口的时候,一些简单的搜索功能基本上是前端去实现的,正好最近用到,写了一个,贴出来和大家分享: 功能描述: 按下键盘后及时搜索条 ...

  3. Android-用webservice连接sqlserver数据库

    以前做的东西,只要用数据库的都是在项目里自己重新做一份数据.但是这种方法是很不可取的,首先,手机内存不会很大,把数据表建在项目里无疑又增大了程序.这样一来手机的运行速度可想而知.其次,数据大的时候还是 ...

  4. PureMVC(JS版)源码解析(八):Proxy类

    前面,我们讲了与视图相关联的Mediator类,接下来我们讲讲与数据相关联的Proxy类. 关于Proxy类的作用,在Proxy类源码中,有这么一段注释:  * In PureMVC, Proxy c ...

  5. 源码解析之–YYAsyncLayer异步绘制

    来源:伯乐在线专栏作者 - Shelin 链接:http://ios.jobbole.com/86878/ 点击 → 了解如何加入专栏作者 前言 YYAsyncLayer是异步绘制与显示的工具.最初是 ...

  6. InnoDB还是MyISAM (摘录)

    两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...

  7. Java Post 数据请求和接收

    这两天在做http服务端请求操作,客户端post数据到服务端后,服务端通过request.getParameter()进行请求,无法读取到数据,搜索了一下发现是因为设置为text/plain模式才导致 ...

  8. Summary: How to calculate PI? Based on Monte Carlo method

    refer to: http://www.stealthcopter.com/blog/2009/09/python-calculating-pi-using-random-numbers/ Duri ...

  9. 认识javascript作用域

    JavaScript的作用域链 这是一个非常重要的知识点了,了解了JavaScript的作用域链的话,能帮助我们理解很多‘异常’问题. 下面我们来看一个小例子,前面我说过的声明提前的例子. var n ...

  10. sql sever怎样替换把表中数据。

    怎样替换把表中“舞台桁架厂”替换为“舞台桁架厂家” 表数据结构为: id                name                    key                addre ...