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

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. Spring boot 内存优化

    转自:https://dzone.com/articles/spring-boot-memory-performance It has sometimes been suggested that Sp ...

  2. VM下的linux系统上不了网?? 使用putty远程登录不上linux的解决方法?

    背景:昨晚想尝试一下用putty远程登录我的linux系统,悲剧的是,我竟然连接不上,显示 connection refused   ,连接被拒绝.于是我就想看看能不能在linux下看看能不能访问百度 ...

  3. adt-bundle-linux-x86_64-20131030下新建project提示找不到adb和R.java问题的解决

    adt-bundle-linux-x86_64-20131030下新建project提示找不到adb和R.java问题的解决 在ubuntu14.04下,搭建Android开发环境,下载官方的adt- ...

  4. C# 如何设置 richTextBoxr的边距

    附件 http://files.cnblogs.com/xe2011/richTextBox_EM_SETRECT.rar using System.Runtime.InteropServices; ...

  5. 在storyboard中的静态UITableView中拖入 UISearchBar and Search Display Controller出现的奇怪问题

         近期学习过程中想模拟一下新浪微博"发现"界面.      我在storyboard中拖入一个UITableViewController,设置这个UITableViewCo ...

  6. GCC内嵌汇编

    http://blog.csdn.net/mydo/article/details/8279924

  7. 模板类之间的友元关系实现Blob和BlobPtr

    16.12编写你自己版本的Blob和BlobPtr模板,包含书中未定义的多个const成员. Blob.h(注意,成员函数的声明和定义要放在一个头文件中) /*记住,模板的头文件中通常既包括声明也包括 ...

  8. mysql 导入excel 或 .csv

    第一步 导出excel 去掉列头,设置文本里面格式

  9. java Thread.join()

    thread1.join()方法阻塞调用此方法的线程,直到线程thread1完成,此线程再继续. 通常用于在main()主线程内,等待其它线程完成再结束main()主线程 @Test /** * ou ...

  10. asp.net网站性能优化2则

    摘要:Web服务器的性能优化有很多资料介绍了,多台主机负载均衡,查询结果的多级缓 存,数据库索引优化等都是常见的优化手段.随着后端优化空间越来越小,现在越来越多 的网站更注重前端性能的优化,就是浏览器 ...