内容简介:特点:先进先出的数据结构分类:串行队列 并行队列 全局并行队列 主队列任务:就是block代码快要执行的代码 同步执行(sync) 异步执行(async)
队列
特点:先进先出的数据结构
分类:串行队列 并行队列 全局并行队列 主队列
任务:就是block代码快要执行的代码 同步执行(sync) 异步执行(async)
多线程 简单理解就是除主线程外开辟了其他线程、增加执行效率。大白话就是代码有多条执行路径。对于单核的iOS系统、多线程之间其实是并发的而不是多核的并行。也就是单核的iOS系统,各个线程在单位时间是来回切换的、造成了并行的假象。
GCD是基于 c语言 封装的、在这里只谈谈用法。用法就是创建队列,将任务添加到队列中执行。
如何创建队列?
串行队列
dispatch_queue_t queue1 = dispatch_queue_create("testQueue", DISPATCH_QUEUE_SERIAL);
主队列 特殊的串行队列---所有主队列的任务都会放在主线程执行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
并行队列
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
全局并行队列
dispatch_queue_t queueAll = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
复制代码
任务
任务分为同步执行、异步执行
同步不具备开启线程的能力
dispatch_sync(queue, ^{
<#code#>
});
异步具备开启线程的能力、具体是否开启了线程要结合队列
dispatch_async(queue1, ^{
<#code#>
});
复制代码
任务和队列组合 page表格截图如下:(由于全局并发队列也可以看作并发队列、所以不予考虑)
一、同步+串行队列
特点:不开启新的线程、任务按顺序执行
- (void)syncSerial {
NSLog(@"当前线程为:%@",[NSThread currentThread]); // 当前线程
NSLog(@"开始");
//这里创建串行队列
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务三、来自线程:%@",[NSThread currentThread]);
}
});
NSLog(@"结束");
}
复制代码
打印结果:
2019-01-23 09:49:41.098930+0800 多线程demo[922:34551] 当前线程为:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:41.099092+0800 多线程demo[922:34551] 开始
2019-01-23 09:49:43.100540+0800 多线程demo[922:34551] 我是任务一、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:45.101953+0800 多线程demo[922:34551] 我是任务一、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:47.103420+0800 多线程demo[922:34551] 我是任务二、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:49.104828+0800 多线程demo[922:34551] 我是任务二、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:51.106334+0800 多线程demo[922:34551] 我是任务三、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:53.106785+0800 多线程demo[922:34551] 我是任务三、来自线程:<NSThread: 0x604000073a80>{number = 1, name = main}
2019-01-23 09:49:53.106981+0800 多线程demo[922:34551] 结束
复制代码
二、同步+并发队列
特点:不开启新的线程、任务按顺序执行
NSLog(@"当前线程%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开始");
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务三、来自线程:%@",[NSThread currentThread]);
}
});
NSLog(@"结束");
复制代码
打印结果:
2019-01-23 10:02:31.505366+0800 多线程demo[1053:44225] 当前线程<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:31.505740+0800 多线程demo[1053:44225] 开始
2019-01-23 10:02:33.506119+0800 多线程demo[1053:44225] 我是任务一、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:35.507093+0800 多线程demo[1053:44225] 我是任务一、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:37.507964+0800 多线程demo[1053:44225] 我是任务二、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:39.508543+0800 多线程demo[1053:44225] 我是任务二、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:41.509973+0800 多线程demo[1053:44225] 我是任务三、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:43.511403+0800 多线程demo[1053:44225] 我是任务三、来自线程:<NSThread: 0x600000064d00>{number = 1, name = main}
2019-01-23 10:02:43.511608+0800 多线程demo[1053:44225] 结束
复制代码
三、异步+串行队列
特点:开启了新的线程、任务顺序执行
NSLog(@"当前线程%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开始");
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务三、来自线程:%@",[NSThread currentThread]);
}
});
NSLog(@"结束");
复制代码
打印结果:
2019-01-23 10:09:26.140699+0800 多线程demo[1116:48819] 当前线程<NSThread: 0x600000076040>{number = 1, name = main}
2019-01-23 10:09:26.140906+0800 多线程demo[1116:48819] 开始
2019-01-23 10:09:26.141049+0800 多线程demo[1116:48819] 结束
2019-01-23 10:09:28.143936+0800 多线程demo[1116:48854] 我是任务一、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
2019-01-23 10:09:30.148732+0800 多线程demo[1116:48854] 我是任务一、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
2019-01-23 10:09:32.154261+0800 多线程demo[1116:48854] 我是任务二、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
2019-01-23 10:09:34.156924+0800 多线程demo[1116:48854] 我是任务二、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
2019-01-23 10:09:36.158106+0800 多线程demo[1116:48854] 我是任务三、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
2019-01-23 10:09:38.162608+0800 多线程demo[1116:48854] 我是任务三、来自线程:<NSThread: 0x6000004629c0>{number = 3, name = (null)}
复制代码
四、异步+并发队列
特点:开启新的线程、任务交替执行
NSLog(@"当前线程%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开始");
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务三、来自线程:%@",[NSThread currentThread]);
}
});
NSLog(@"结束");
复制代码
打印结果:
2019-01-23 10:15:29.424356+0800 多线程demo[1190:53683] 当前线程<NSThread: 0x604000074740>{number = 1, name = main}
2019-01-23 10:15:29.424575+0800 多线程demo[1190:53683] 开始
2019-01-23 10:15:29.424723+0800 多线程demo[1190:53683] 结束
2019-01-23 10:15:31.430195+0800 多线程demo[1190:53767] 我是任务三、来自线程:<NSThread: 0x60400047f5c0>{number = 5, name = (null)}
2019-01-23 10:15:31.430195+0800 多线程demo[1190:53764] 我是任务二、来自线程:<NSThread: 0x600000278a80>{number = 3, name = (null)}
2019-01-23 10:15:31.430195+0800 多线程demo[1190:53763] 我是任务一、来自线程:<NSThread: 0x60400047fe40>{number = 4, name = (null)}
2019-01-23 10:15:33.435111+0800 多线程demo[1190:53763] 我是任务一、来自线程:<NSThread: 0x60400047fe40>{number = 4, name = (null)}
2019-01-23 10:15:33.435111+0800 多线程demo[1190:53767] 我是任务三、来自线程:<NSThread: 0x60400047f5c0>{number = 5, name = (null)}
2019-01-23 10:15:33.435111+0800 多线程demo[1190:53764] 我是任务二、来自线程:<NSThread: 0x600000278a80>{number = 3, name = (null)}
复制代码
五、异步+主队列(任务执行 类似为同步+串行队列)
特点:主线程执行(主队列的任务都是在主线程)、任务按顺序执行
NSLog(@"当前线程为:%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开始");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]); // 打印当前线程
}
});
dispatch_async(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"我是任务三、来自线程:%@",[NSThread currentThread]); // 打印当前线程
}
});
NSLog(@"结束");
复制代码
打印结果:
2019-01-23 10:19:33.503411+0800 多线程demo[1242:56892] 当前线程为:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:33.503588+0800 多线程demo[1242:56892] 开始
2019-01-23 10:19:33.503736+0800 多线程demo[1242:56892] 结束
2019-01-23 10:19:35.538348+0800 多线程demo[1242:56892] 我是任务一、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:37.539726+0800 多线程demo[1242:56892] 我是任务一、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:39.541125+0800 多线程demo[1242:56892] 我是任务二、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:41.542511+0800 多线程demo[1242:56892] 我是任务二、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:43.543439+0800 多线程demo[1242:56892] 我是任务三、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
2019-01-23 10:19:45.544663+0800 多线程demo[1242:56892] 我是任务三、来自线程:<NSThread: 0x60000006eac0>{number = 1, name = main}
复制代码
六、同步+主队列
特点:队列引起的死锁
- (void)syncMain {
NSLog(@"当前线程:%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开始");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务一、来自线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"我是任务二、来自线程:%@",[NSThread currentThread]);
}
});
NSLog(@"结束");
}
复制代码
打印结果:
2019-01-23 10:25:00.640438+0800 多线程demo[1307:61022] 当前线程:<NSThread: 0x600000069a80>{number = 1, name = main}
2019-01-23 10:25:00.640607+0800 多线程demo[1307:61022] 开始
(lldb) 崩溃
复制代码
分析:由于主队列是串行队列、我们把syncMain方法看成一个任务、任务一看成一个任务。由于这两个任务都在主队列执行。主队列是特殊的串行队列。特点是任务按顺序执行。所以先执行syncMain、而syncMain要等任务一执行完才能结束。任务一要等syncMain结束再执行。两个任务互相等待。造成死锁。这就是为什么同步在主队列执行会死锁而同步在串行队列不死锁的原因。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 045.Python线程队列
- Callable,阻塞队列,线程池问题
- 面试官:线程池运行机制如何改为线程池满了,再丢队列?
- 数据结构与算法:队列:队列在线程池等有限资源池中的应用
- 踩坑 Spring Cloud Hystrix 线程池队列配置
- c# – 使用线程处理队列的最有效的方式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web应用漏洞侦测与防御
Mike Shema / 齐宁、庞建民、张铮、单征 / 机械工业出版社 / 2014-8-20 / 69.00
本书由国际知名网络安全专家亲笔撰写,全面讲解如何预防常见的网络攻击,包括HTML注入及跨站脚本攻击、跨站请求伪造攻击、SQL注入攻击及数据存储操纵、攻破身份认证模式、利用设计缺陷、利用平台弱点、攻击浏览器和隐私等, 全书共8章:第1章介绍HTML5的新增特性及使用和滥用HTML5的安全考虑;第2章展示了如何只通过浏览器和最基本的HTML知识就可以利用Web中最常见的漏洞;第3章详细讲解CSR......一起来看看 《Web应用漏洞侦测与防御》 这本书的介绍吧!