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

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. 深入理解Objective-C:优化你的代码

    开篇 只要用到Objective-C,我们每天都会跟方法调用打交道.我们都知道Objective-C的方法决议是动态的,但是在底层一个方法究竟是怎么找到的,方法缓存又是怎么运作的却鲜为人知. 本文主要 ...

  2. Android——打造万能适配器(CommonAdapter)

    List<T> : ListView -> Adapter extends BaseAdapter -> ViewHolder ViewHolder CommonAdaper ...

  3. 【设计模式 - 22】之策略模式(Strategy)

    1      模式简介 在策略模式中,一个类的行为或其算法可以在运行时改变.策略模式定义了一系列算法,把它们一个个封装起来,并且使它们可以互相替换. 策略模式的优点: 1)        算法可以自由 ...

  4. 非常棒的jqChart图表插件

    由于项目需要,做一些类似于OA系统的应用时,表格用到的是最多的,那么图表展示就先显得尤为的重要,其中柱柱状图.折线图.饼状图又居多. 之前一直使用的是Chrome下的googleAPI中提供的char ...

  5. Android仿微信UI布局视图(圆角布局的实现)

    圆角button.或布局能够在xml文件里实现,但也能够使用图片直接达到所需的效果,曾经版本号的微信就使用了这样的方法. 实现效果图:    watermark/2/text/aHR0cDovL2Js ...

  6. APUE 读书笔记 -----孤儿进程与僵尸进程[总结] +数据结构+C

    http://www.cnblogs.com/Anker/p/3271773.html

  7. HDU 4196 Remoteland

    题意:给定一个n,然后让你从1-n中选出某些数乘起来,使得乘积最大,并且乘积必须是完全平方数. 思路:将1-n种每个数都分解素因子,把他们的素因子的幂加起来,如果是偶数,就说明可以构成完全平方数,乘起 ...

  8. 图像本地预览插件(基于JQUERY、HTML5)

    最近是被这项目搞疯了.害我天天写插件,上周才写,现在就继续吧..... 说说这个吧.主要是用于本地图像预览的.我们知道在以前,图像预览一般都很麻烦,一般都是异步上传然后返回路径,动态设置路径,但是这样 ...

  9. Java 之 MYSQL 数据库搭建

    1.首先要去加载java的mysql驱动,将下载的mysql-connect-bin-java.jar包添加到该项目下2.然后通过 Class.forName("com.mysql.jdbc ...

  10. A题笔记(3)

    No. 1381 容器相关 #include <vector> 头文件 vector<Presents> present; present.push_back(name); 向 ...