GCD中任务与队列(一)
来源:互联网 发布:淘宝老店铺 编辑:程序博客网 时间:2024/05/19 08:44
首先,GCD是一套基于C的并发编程(其实并不能理解为多线程,因为这个并不是自己来控制线程),使用的时候,我们不需要管理线程的任何生命周期,系统会自动帮我们管理。首先在底层是有一个任务队列与线程池的概念,如果这个不懂,百度一下先。其次先理解以下几个概念。
1、同步、异步
同步:表示在当前线程(注意:不一定就表示主线程)执行任务,不去线程池中拿线程
异步:表示不在当前线程执行任务,需要去线程池拿线程做处理
2、串行、并发
串行:表示所有任务一个接一个的在线程中执行
并发:表示所有任务可以同时在不同线程上执行
可能这样粗略讲解一下,还是不够清晰,先我们这样理解一下,同步,异步是用来表示是否需要去线程池中取线程,而串行、并发是用来表示怎么去任务队列中取任务的。
下面我们组合一下上面两种方式通过代码来一一讲解。
1、同步、串行 (在当前线程中一个一个的执行任务)
/** 串行、同步 */- (void)demo1 { //创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_SERIAL); NSLog(@"start ==>> %@", [NSThread currentThread]); //同步执行任务 for (NSInteger i = 0; i < 10; i++) { dispatch_sync(queue, ^{ [NSThread sleepForTimeInterval:0.5]; NSLog(@"%zd -- %@", i, [NSThread currentThread]); }); } NSLog(@"stop ==>> %@", [NSThread currentThread]);}
执行结果:
2017-09-01 14:04:22.728 GCDTest[15085:1120147] start ==>> <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:23.230 GCDTest[15085:1120147] 0 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:23.731 GCDTest[15085:1120147] 1 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:24.232 GCDTest[15085:1120147] 2 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:24.733 GCDTest[15085:1120147] 3 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:25.234 GCDTest[15085:1120147] 4 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:25.736 GCDTest[15085:1120147] 5 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:26.236 GCDTest[15085:1120147] 6 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:26.738 GCDTest[15085:1120147] 7 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.238 GCDTest[15085:1120147] 8 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.739 GCDTest[15085:1120147] 9 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.739 GCDTest[15085:1120147] stop ==>> <NSThread: 0x600000064c80>{number = 1, name = main}
从执行结果可以看到,所有任务都是一个一个的执行.
2、异步串行 (会去线程池拿线程,但是任务顺序执行)
/** 串行、异步 */- (void)demo2 { //创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_SERIAL); NSLog(@"start ==>> %@", [NSThread currentThread]); //同步执行任务 for (NSInteger i = 0; i < 10; i++) { dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:0.5]; NSLog(@"%zd -- %@", i, [NSThread currentThread]); }); } NSLog(@"stop ==>> %@", [NSThread currentThread]);}
执行结果:
2017-09-01 14:09:43.919 GCDTest[15254:1145817] start ==>> <NSThread: 0x610000070080>{number = 1, name = main}2017-09-01 14:09:43.919 GCDTest[15254:1145817] stop ==>> <NSThread: 0x610000070080>{number = 1, name = main}2017-09-01 14:09:44.422 GCDTest[15254:1146187] 0 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:44.926 GCDTest[15254:1146187] 1 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:45.430 GCDTest[15254:1146187] 2 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:45.930 GCDTest[15254:1146187] 3 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:46.435 GCDTest[15254:1146187] 4 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:46.940 GCDTest[15254:1146187] 5 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:47.441 GCDTest[15254:1146187] 6 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:47.945 GCDTest[15254:1146187] 7 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:48.453 GCDTest[15254:1146187] 8 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:48.956 GCDTest[15254:1146187] 9 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}
由以上结果可以知道,start、stop 在主线程中执行完成,其他的开辟了一个子线程执行
3、同步并发 (在当前队列执行,可以同时取出多个任务(取出那么多任务,只有一个线程,有鸟用))上代码
/** 并发、同步 */- (void)demo3 { //创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_CONCURRENT); NSLog(@"start ==>> %@", [NSThread currentThread]); //同步执行任务 for (NSInteger i = 0; i < 10; i++) { dispatch_sync(queue, ^{ [NSThread sleepForTimeInterval:0.5]; NSLog(@"%zd -- %@", i, [NSThread currentThread]); }); } NSLog(@"stop ==>> %@", [NSThread currentThread]);}
执行结果:
2017-09-01 14:14:02.972 GCDTest[15403:1168682] start ==>> <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:03.473 GCDTest[15403:1168682] 0 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:03.974 GCDTest[15403:1168682] 1 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:04.476 GCDTest[15403:1168682] 2 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:04.976 GCDTest[15403:1168682] 3 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:05.477 GCDTest[15403:1168682] 4 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:05.978 GCDTest[15403:1168682] 5 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:06.478 GCDTest[15403:1168682] 6 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:06.979 GCDTest[15403:1168682] 7 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.481 GCDTest[15403:1168682] 8 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.982 GCDTest[15403:1168682] 9 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.982 GCDTest[15403:1168682] stop ==>> <NSThread: 0x618000078380>{number = 1, name = main}
看上面就知道,所有任务都在主线程中执行,所以取出来的任务还是得等待
4、并发、异步(拿线程,同时拿任务) 这才是多线程的精髓,上代码
/** 并发、异步 */- (void)demo4 { //创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_CONCURRENT); NSLog(@"start ==>> %@", [NSThread currentThread]); //同步执行任务 for (NSInteger i = 0; i < 10; i++) { dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:0.5]; NSLog(@"%zd -- %@", i, [NSThread currentThread]); }); } NSLog(@"stop ==>> %@", [NSThread currentThread]);}
执行结果
2017-09-01 14:20:28.223 GCDTest[15696:1210937] start ==>> <NSThread: 0x600000076900>{number = 1, name = main}2017-09-01 14:20:28.223 GCDTest[15696:1210937] stop ==>> <NSThread: 0x600000076900>{number = 1, name = main}2017-09-01 14:20:28.223 GCDTest[15696:1211285] 1 -- <NSThread: 0x608000077940>{number = 3, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211286] 3 -- <NSThread: 0x600000079340>{number = 6, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211307] 2 -- <NSThread: 0x600000079280>{number = 5, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211306] 0 -- <NSThread: 0x61000007a300>{number = 4, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211288] 4 -- <NSThread: 0x61000007a140>{number = 7, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211563] 5 -- <NSThread: 0x6180000794c0>{number = 8, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211564] 6 -- <NSThread: 0x600000079300>{number = 9, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211565] 7 -- <NSThread: 0x600000079480>{number = 10, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211285] 8 -- <NSThread: 0x608000077940>{number = 3, name = (null)}2017-09-01 14:20:28.224 GCDTest[15696:1211286] 9 -- <NSThread: 0x600000079340>{number = 6, name = (null)}
从上可以看出,start,stop是在主线程中完成,其他的开了多个队列再执行,至于具体的任务在哪条线程上执行,这就是GCD底层控制的,所以这也就说明了GCD不能叫做多线程,只能叫并发编程
- GCD中任务与队列(一)
- GCD队列与任务
- GCD中的队列与任务
- GCD中的队列与任务组合对比
- GCD任务、队列理解
- iOS中多线程知识总结:进程、线程、GCD、串行队列、并行队列、全局队列、主线程队列、同步任务、异步任务等(有示例代码)
- 理解GCD中任务和队列执行的原理
- 多线程GCD的详细讲解 任务和队列(串行队列,并发队列) (一)
- GCD任务队列机制解析
- GCD与队列
- iOS中多线程知识总结:进程、线程、GCD、串行队列、并行队列、全局队列、主线程队列、同步任务、异步任务等
- 苹果多线程网络编程之-GCD队列与任务的理解
- GCD:dispatch_sync会在当前线程中执行派发到其他队列的任务
- PHP队列研究一(数据库任务队列)
- GCD 基础 (队列)
- GCD之串行队列与并发队列
- Oracle中任务队列
- 猫猫学iOS(五十)多线程网络之GCD简单介绍(任务,队列)
- Retrofit 2.2 传递数组参数
- python教程之二-----一个Python的非正式介绍
- squirrel-foundation状态机的使用细节
- sql 优化注意事项
- 静态链接的整个过程
- GCD中任务与队列(一)
- 简单斐波那契
- 单选,反选,全选
- 负载均衡基础知识
- 从ttf原始文件解析出字体名称时遇到的字节序的问题是big endian
- Android官方DataBinding(十一):对双向绑定之反向绑定的改进和简化
- python gutenberg古腾堡语料库
- HttpClient大并发下Timeout waiting for connection from pool 问题解决方案
- 2012-2013 Northwestern European Regional Contest (NWERC 2012)【solved:6 / 11】