多线程队列是装载线程任务的队形结构。(系统以先进先出的方式调度队列中的任务执行 FIFO)。在GCD中有两种队列:

串行队列、并发队列。

队列 :串行队列、并发队列,全局主对列,全局并发队列

2.1.  串行队列:线程只能依次有序的执行。

2.1.1 串行方法 1

- (void)SerialQueueOne{

    NSLog(@"串行1 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

    dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"串行1 index %d ::: %@",i,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"串行1 index %d ::: %@",i,[NSThread currentThread]);
}
});
NSLog(@"串行1 end :::%@",[NSThread currentThread]);
}

执行结果:::

2017-12-20 13:49:47.427330+0800 DeadThread[8972:2450330] 串行1 start :::<NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427470+0800 DeadThread[8972:2450330] 串行1 index 0 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427567+0800 DeadThread[8972:2450330] 串行1 index 1 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427636+0800 DeadThread[8972:2450330] 串行1 index 2 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427696+0800 DeadThread[8972:2450330] 串行1 index 10 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427819+0800 DeadThread[8972:2450330] 串行1 index 11 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427893+0800 DeadThread[8972:2450330] 串行1 index 12 ::: <NSThread: 0x60800006ae80>{number = 1, name = main}
2017-12-20 13:49:47.427966+0800 DeadThread[8972:2450330] 串行1 end :::<NSThread: 0x60800006ae80>{number = 1, name = main}

得到结果:::

1.代码顺序 执行;

2.1.2 串行方法 2

- (void)SerialQueueTwo{

    NSLog(@"串行2 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

   dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"串行2 index %d ::: %@",i,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"串行2 index %d ::: %@",i,[NSThread currentThread]);
}
}); NSLog(@"串行2 end :::%@",[NSThread currentThread]);
}

执行结果:::

2017-12-20 13:50:47.130380+0800 DeadThread[8993:2458517] 串行1 start :::<NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.130533+0800 DeadThread[8993:2458517] 串行1 index 0 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.130648+0800 DeadThread[8993:2458517] 串行1 index 1 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.130724+0800 DeadThread[8993:2458517] 串行1 index 2 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.130896+0800 DeadThread[8993:2458517] 串行1 index 10 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.130979+0800 DeadThread[8993:2458517] 串行1 index 11 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.131057+0800 DeadThread[8993:2458517] 串行1 index 12 ::: <NSThread: 0x60c000071300>{number = 1, name = main}
2017-12-20 13:50:47.131130+0800 DeadThread[8993:2458517] 串行1 end :::<NSThread: 0x60c000071300>{number = 1, name = main}

得到结果:::

1.没有开启线程

2.代码顺序执行;

2.2 并发队列:线程可以同时一起进行执行。实际上是CPU在多条线程之间快速的切换。(并发功能只有在异步(dispatch_async)函数下才有效)

2.2.1 并发方法 1

- (void)concurrentQueueOne{

    NSLog(@"并发1 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);

    dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"并发1 index %d ::: %@",i,[NSThread currentThread]);
}
}); dispatch_sync(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"并发1 index %d ::: %@",i,[NSThread currentThread]);
}
}); NSLog(@"并发1 end :::%@",[NSThread currentThread]);
}

执行结果:::

2017-12-20 13:52:37.606997+0800 DeadThread[9023:2470506] 并发1 start :::<NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.607130+0800 DeadThread[9023:2470506] 并发1 index 0 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.607197+0800 DeadThread[9023:2470506] 并发1 index 1 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.607447+0800 DeadThread[9023:2470506] 并发1 index 2 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.607685+0800 DeadThread[9023:2470506] 并发1 index 10 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.607891+0800 DeadThread[9023:2470506] 并发1 index 11 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.608056+0800 DeadThread[9023:2470506] 并发1 index 12 ::: <NSThread: 0x608000261600>{number = 1, name = main}
2017-12-20 13:52:37.608190+0800 DeadThread[9023:2470506] 并发1 end :::<NSThread: 0x608000261600>{number = 1, name = main}

得到结果:::

1.线程顺序执行

2.2.2 并发方法 2

- (void)concurrentQueueTwo{

    NSLog(@"并发2 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"并发2 index %d ::: %@",i,[NSThread currentThread]);
}
}); dispatch_async(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"并发2 index %d ::: %@",i,[NSThread currentThread]);
}
}); NSLog(@"并发2 end :::%@",[NSThread currentThread]);
}

执行结果::;

2017-12-20 13:56:45.573695+0800 DeadThread[9084:2492640] 并发2 start :::<NSThread: 0x604000077d80>{number = 1, name = main}
2017-12-20 13:56:45.573891+0800 DeadThread[9084:2492640] 并发2 end :::<NSThread: 0x604000077d80>{number = 1, name = main}
2017-12-20 13:56:45.573907+0800 DeadThread[9084:2492674] 并发2 index 0 ::: <NSThread: 0x60c000265a40>{number = 3, name = (null)}
2017-12-20 13:56:45.573908+0800 DeadThread[9084:2492675] 并发2 index 10 ::: <NSThread: 0x60400026f000>{number = 4, name = (null)}
2017-12-20 13:56:45.574283+0800 DeadThread[9084:2492674] 并发2 index 1 ::: <NSThread: 0x60c000265a40>{number = 3, name = (null)}
2017-12-20 13:56:45.574344+0800 DeadThread[9084:2492675] 并发2 index 11 ::: <NSThread: 0x60400026f000>{number = 4, name = (null)}
2017-12-20 13:56:45.574420+0800 DeadThread[9084:2492675] 并发2 index 12 ::: <NSThread: 0x60400026f000>{number = 4, name = (null)}
2017-12-20 13:56:45.574422+0800 DeadThread[9084:2492674] 并发2 index 2 ::: <NSThread: 0x60c000265a40>{number = 3, name = (null)}

得到结果:::

1.添加两个 任务代码块,开启两个线程;

2.子线程中代码 不是按顺序执行

2.3 全局主队列::::

2.3.1  主队列 同步 死锁

- (void)syncMain {

    NSLog(@"\n\n**************主队列同步,放到主线程会死锁***************\n\n");

    // 主队列
dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列同步1 %@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列同步2 %@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列同步3 %@",[NSThread currentThread]);
}
});
}

死锁原因:::

    如果在主线程中运用主队列同步,也就是把任务放到了主线程的队列中。

    而同步对于任务是立刻执行的,那么当把第一个任务放进主队列时,它就会立马执行。

    可是主线程现在正在处理syncMain方法,任务需要等syncMain执行完才能执行。

    syncMain执行到第一个任务的时候,又要等第一个任务执行完才能往下执行第二个和第三个任务。

    这样syncMain方法和第一个任务就开始了互相等待,形成了死锁。

2.3.2  主队列 异步

- (void)asyncMain {

    NSLog(@"**************主队列异步***************");

    // 主队列
dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列异步1 %@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列异步2 %@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"主队列异步3 %@",[NSThread currentThread]);
}
});
}

执行结果:::

2017-12-20 14:20:01.729412+0800 DeadThread[9257:2636939] **************主队列异步***************
2017-12-20 14:20:01.732208+0800 DeadThread[9257:2636939] 主队列异步1 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.732326+0800 DeadThread[9257:2636939] 主队列异步1 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.732456+0800 DeadThread[9257:2636939] 主队列异步1 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.732726+0800 DeadThread[9257:2636939] 主队列异步2 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.732931+0800 DeadThread[9257:2636939] 主队列异步2 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.733026+0800 DeadThread[9257:2636939] 主队列异步2 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.733128+0800 DeadThread[9257:2636939] 主队列异步3 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.733251+0800 DeadThread[9257:2636939] 主队列异步3 <NSThread: 0x604000261080>{number = 1, name = main}
2017-12-20 14:20:01.733502+0800 DeadThread[9257:2636939] 主队列异步3 <NSThread: 0x604000261080>{number = 1, name = main}

得到结果:::

1. 主队列是个同步队列

2.4 全局并发队列

2.4.1

- (void)globalQueueOne{

    NSLog(@"global1 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

    dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"global1 index %d ::: %@",i,[NSThread currentThread]);
}
}); dispatch_sync(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"global1 index %d ::: %@",i,[NSThread currentThread]);
}
}); NSLog(@"global1 end :::%@",[NSThread currentThread]);
}

执行结果:::

2017-12-20 14:27:02.302953+0800 DeadThread[9352:2669397] global1 start :::<NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303132+0800 DeadThread[9352:2669397] global1 index 0 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303230+0800 DeadThread[9352:2669397] global1 index 1 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303322+0800 DeadThread[9352:2669397] global1 index 2 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303397+0800 DeadThread[9352:2669397] global1 index 10 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303467+0800 DeadThread[9352:2669397] global1 index 11 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303557+0800 DeadThread[9352:2669397] global1 index 12 ::: <NSThread: 0x6000000655c0>{number = 1, name = main}
2017-12-20 14:27:02.303638+0800 DeadThread[9352:2669397] global1 end :::<NSThread: 0x6000000655c0>{number = 1, name = main}

2.4.2

- (void)globalQueueTwo{

    NSLog(@"global2 start :::%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"global2 index %d ::: %@",i,[NSThread currentThread]);
}
}); dispatch_async(queue, ^{
for (int i = 10; i < 13; i++) {
NSLog(@"global2 index %d ::: %@",i,[NSThread currentThread]);
}
}); NSLog(@"global2 end :::%@",[NSThread currentThread]);
}

执行结果:::

2017-12-20 14:28:27.498062+0800 DeadThread[9382:2678820] global2 start :::<NSThread: 0x600000076700>{number = 1, name = main}
2017-12-20 14:28:27.498208+0800 DeadThread[9382:2678820] global2 end :::<NSThread: 0x600000076700>{number = 1, name = main}
2017-12-20 14:28:27.498250+0800 DeadThread[9382:2679707] global2 index 0 ::: <NSThread: 0x60c0000779c0>{number = 3, name = (null)}
2017-12-20 14:28:27.498260+0800 DeadThread[9382:2679706] global2 index 10 ::: <NSThread: 0x60400007e800>{number = 4, name = (null)}
2017-12-20 14:28:27.498555+0800 DeadThread[9382:2679707] global2 index 1 ::: <NSThread: 0x60c0000779c0>{number = 3, name = (null)}
2017-12-20 14:28:27.498692+0800 DeadThread[9382:2679706] global2 index 11 ::: <NSThread: 0x60400007e800>{number = 4, name = (null)}
2017-12-20 14:28:27.498710+0800 DeadThread[9382:2679707] global2 index 2 ::: <NSThread: 0x60c0000779c0>{number = 3, name = (null)}
2017-12-20 14:28:27.498753+0800 DeadThread[9382:2679706] global2 index 12 ::: <NSThread: 0x60400007e800>{number = 4, name = (null)}

iOS 多线程的简单理解(2) 队列 :串行 ,并行,MainQueue,GlobalQueue的更多相关文章

  1. ios多线程操作(五)—— GCD串行队列与并发队列

          GCD的队列能够分为2大类型,分别为串行队列和并发队列      串行队列(Serial Dispatch Queue):      一次仅仅调度一个任务,队列中的任务一个接着一个地运行( ...

  2. iOS 多线程的简单理解(3)执行方式 + 执行对列 的组合

    通过对前面两偏线程理解的总结,自己对线程的理解也逐渐加深,梳理的清晰起来…… 通常在使用线程 的时候,都是要用到 执行对列,执行方式,执行任务, 现在开始新一轮的深入 3. 1. 1  同步 + 串行 ...

  3. iOS:GCD理解1(串行-并行、同步-异步)

    1.获取并行.创建串行 队列 1-1).获取 并行(全局) 队列 ,DISPATCH_QUEUE_PRIORITY_DEFAULT 为默认优先级. dispatch_queue_t global_qu ...

  4. iOS 多线程的简单理解(4) 线程锁的简单使用

    要用到多线程 ,就不得不考虑,线程之间的交互,线程是否安全 推荐一个原文链接 是关于 线程锁的基本使用的  http://blog.csdn.net/qq_30513483/article/detai ...

  5. iOS 多线程的简单理解(1) 方式 :同步 异步

    最近遇到特别糟糕的面试,过程中提到多次对多线程的处理问题,并没有很好的给予答复和解决,所以在这里做个简单的备案: 期望能更加了解和熟练使用 多线程技术: 下面都是自己的总结,如果存在不对的,或者不足, ...

  6. IOS多线程知识总结/队列概念/GCD/串行/并行/同步/异步

    进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间: 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程. 队列:dis ...

  7. iOS多线程——同步异步串行并行

    串行并行异步同步的概念很容易让人混淆,关于这几个概念我在第一篇GCD中有解释,但是还不够清晰,所以这里重写一篇博客专门对这几个概念进行区分: 先说一下队列和任务: (1)队列分为串行和并行,任务的执行 ...

  8. 【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

    (1)GCD实现的同步异步.串行并行. --同步sync应用场景:用户登录,利用堵塞 --串行异步应用场景:下载等耗时间的任务 /** * 由于是异步.所以开通了子线程.可是由于是串行队列,所以仅仅须 ...

  9. GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

    转:http://www.tuicool.com/articles/NVVnMn (1)GCD实现的同步异步.串行并行. ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等耗时 ...

随机推荐

  1. Hive ACID和事务表支持详解

    一.ACID介绍 ACID就是常见数据库事务的四大特性:Atomicity(原子性).Consistency(一致性).Isolation(隔离性).Durability(持久性). 在Hive 0. ...

  2. Go Node.js 生成的exe公布成windows服务

    环境变量 GOBIN E:\01_SOFT\go1.9.2\bin GOROOT E:\01_SOFT\go1.9.2 GOPATH(下载包的存放位置:go get github.com/gin-go ...

  3. learning java swing 基本组件用法

    import javax.swing.*; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event ...

  4. WSAStartup() - 使用方法

    当一个应用程序调用WSAStartup函数时, 操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中. 以后应用程序就可以调用所请求的Socket库 ...

  5. QEventLoop以及QT事件循环

    1.一般我们的事件循环都是由exec()来开启的,例如下面的例子: 1 QCoreApplicaton::exec() 2 QApplication::exec() 3 QDialog::exec() ...

  6. HTML5全屏操作API

    一.定义:HTML5规范允许自定义网页上的任一元素全屏显示,存在兼容问题 二.使用: ①基本: Node.RequestFullScreen()开启全屏显示 Node.CancelFullScreen ...

  7. BZOJ 1406: [AHOI2007]密码箱

    二次联通门 : BZOJ 1406: [AHOI2007]密码箱 /* BZOJ 1406: [AHOI2007]密码箱 数论 要求 x^2 ≡ 1 (mod n) 可以转换为 x ^ 2 - k * ...

  8. Ceph osd故障恢复

    1  调高osd的日志等级 加上红框那一行就可以了 osd的日志路径:/var/log/ceph/ceph-osd.3.log 注意:加上了这一行后日志会刷很多,所以要特别注意日志容量的变化,以防把v ...

  9. 关于Lombok的认识及其应用(一)

    目录 1.Lombok的介绍 2.Lombok的安装 3.Lombok实现原理分析 4.Lombok使用方法 4.1.@Data注解 4.2.@Getter/@Setter注解 1.Lombok的介绍 ...

  10. 【随记】Sql Server 2008 R2 备份时“无法打开备份设备”

    如下图所示,在执行SQL一个简单的备份命令时发生下面的错误 可能的原因: 1.文件夹权限问题: 2.Sql Server SQLServer服务器用户策略问题: 问题排查: 1.查看了temp文件夹, ...