首页 > 移动平台 > 详细

IOS-线程(GCD)

时间:2016-01-17 20:15:56      阅读:275      评论:0      收藏:0      [点我收藏+]

一、GCD的使用

  1 //
  2 //  ViewController.m
  3 //  IOS_0117_GCD
  4 //
  5 //  Created by ma c on 16/1/17.
  6 //  Copyright (c) 2016年 博文科技. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 
 11 @interface ViewController ()
 12 
 13 @end
 14 /*
 15  一、简介
 16  1.什么是GCD
 17  全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
 18  纯C语言,提供了非常多强大的函数
 19  
 20  2.GCD的优势
 21  GCD是苹果公司为多核的并行运算提出的解决方案
 22  GCD会自动利用更多的CPU内核(比如双核、四核)
 23  GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
 24  程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
 25  
 26  二、任务和队列
 27  1.GCD中有2个核心概念
 28  任务:执行什么操作
 29  队列:用来存放任务
 30  
 31  2.GCD的使用就2个步骤
 32  定制任务
 33  确定想做的事情
 34  
 35  3.将任务添加到队列中
 36  GCD会自动将队列中的任务取出,放到对应的线程中执行
 37  任务的取出遵循队列的FIFO原则:先进先出,后进后出
 38  
 39  三、执行任务
 40  1.GCD中有2个用来执行任务的函数
 41  用同步的方式执行任务
 42  dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
 43  queue:队列
 44  block:任务
 45  
 46  2.用异步的方式执行任务
 47  dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
 48  
 49  3.同步和异步的区别
 50  同步:只能在当前线程中执行任务,不具备开启新线程的能力
 51  异步:可以在新的线程中执行任务,具备开启新线程的能力
 52  
 53  四、队列的类型
 54  1.GCD的队列可以分为2大类型
 55  并发队列(Concurrent Dispatch Queue)
 56  可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
 57  并发功能只有在异步(dispatch_async)函数下才有效
 58  
 59  2.串行队列(Serial Dispatch Queue)
 60  让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
 61  
 62  五、容易混淆的术语
 63  1.有4个术语比较容易混淆:同步、异步、并发、串行
 64  同步和异步主要影响:能不能开启新的线程
 65  同步:在当前线程中执行任务,不具备开启新线程的能力
 66  异步:在新的线程中执行任务,具备开启新线程的能力
 67  
 68  2.并发和串行主要影响:任务的执行方式
 69  并发:多个任务并发(同时)执行
 70  串行:一个任务执行完毕后,再执行下一个任务
 71  
 72 
 73 
 74  同步串行:在一个与主线程同步的线程中,同步执行任务
 75  ps:在计算机中除了主线程外,其余线程都是并行性质
 76  异步串行:在与一个主线程不同步的线程中,异步执行任务
 77  
 78  同步并行:线程中多个任务同时向前推进
 79  异步并行:线程中多个任务同时进行,但完成度不同
 80  
 81  六、并发队列
 82  1.GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
 83  使用dispatch_get_global_queue函数获得全局的并发队列
 84  dispatch_queue_t dispatch_get_global_queue(
 85  dispatch_queue_priority_t priority, // 队列的优先级
 86  unsigned long flags); // 此参数暂时无用,用0即可
 87  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 获得全局并发队列
 88  
 89  2.全局并发队列的优先级
 90  #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
 91  #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
 92  #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
 93  #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
 94  
 95  七、串行队列
 96  1.GCD中获得串行有2种途径
 97  使用dispatch_queue_create函数创建串行队列
 98  dispatch_queue_t
 99  dispatch_queue_create(const char *label, // 队列名称
100  dispatch_queue_attr_t attr); // 队列属性,一般用NULL即可
101  dispatch_queue_t queue = dispatch_queue_create("cn.itcast.queue", NULL); // 创建
102  dispatch_release(queue); // 非ARC需要释放手动创建的队列
103  
104  2.使用主队列(跟主线程相关联的队列)
105  主队列是GCD自带的一种特殊的串行队列
106  放在主队列中的任务,都会放到主线程中执行
107  使用dispatch_get_main_queue()获得主队列
108  dispatch_queue_t queue = dispatch_get_main_queue();
109  
110  八、各种队列的执行效果
111  注意
112  使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列
113  
114  九、线程间通信示例
115  1.从子线程回到主线程
116  dispatch_async(
117  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
118  // 执行耗时的异步操作...
119  dispatch_async(dispatch_get_main_queue(), ^{
120  // 回到主线程,执行UI刷新操作
121  });
122  });
123  
124  十、延时执行
125  iOS常见的延时执行有2种方式
126  调用NSObject的方法
127  [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
128  // 2秒后再调用self的run方法
129  
130  使用GCD函数
131  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
132  // 2秒后执行这里的代码... 在哪个线程执行,跟队列类型有关
133  
134  });
135  
136  十一、一次性代码
137  使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
138  static dispatch_once_t onceToken;
139  dispatch_once(&onceToken, ^{
140  // 只执行1次的代码(这里面默认是线程安全的)
141  });
142  
143  十二、队列组
144  1.有这么1种需求
145  首先:分别异步执行2个耗时的操作
146  其次:等2个异步操作都执行完毕后,再回到主线程执行操作
147  
148  2.如果想要快速高效地实现上述需求,可以考虑用队列组
149  dispatch_group_t group =  dispatch_group_create();
150  dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
151  // 执行1个耗时的异步操作
152  });
153  dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
154  // 执行1个耗时的异步操作
155  });
156  dispatch_group_notify(group, dispatch_get_main_queue(), ^{
157  // 等前面的异步操作都执行完毕后,回到主线程...
158  });
159  
160  十三、Core Foundation
161  Foundation : OC
162  Core Foundation : C
163  Foundation和Core Foundation可以相互转化
164  
165  NSString *str = @"123";
166  CFStringRef str2 = (__bridge CFStringRef)str;
167  NSString *str3 = (__bridge NSString *)(str2);
168  
169  CFArrayRef --- NSArray
170  CFDictionaryRef --- NSDirectory
171  CFNumberRef --- NSNumber
172  
173  凡是函数名中带有create\copy\retain\new等字眼,都应该再不需要的时候进行release
174  GCD的数据类型在ARC环境下不需要release
175  CF(Core Foundation)的数据类型在ARC环境下还需要release
176  
177  Core Foundation中手动创建的数据类型,需要手动释放
178  CFArrayRef array = CFArrayCreate(NULL, NULL, 10, NULL);
179  CFRelease(array);
180  
181  CGPathRef path = CGPathCreateMutable();
182  CGPathRelease(path);
183  
184  */
185 @implementation ViewController
186 
187 - (void)viewDidLoad {
188     [super viewDidLoad];
189     
190 }
191 
192 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
193 {
194 //    [self basicUse];
195     
196 //    [self asyncGlobleQueue];
197 //    [self asyncSerialQueue];
198 //    [self asyncMainQueue];
199     
200 //    [self syncGlobleQueue];
201 //    [self syncSerialQueue];
202 //    [self syncMainQueue];
203 }
204 
205 #pragma mark - 异步
206 
207 /**
208  * async(异步) --并发队列(最常用)
209  * 会不会创建线程:会,并且创建多条线程
210  * 任务的执行方式:并发执行
211  */
212 - (void)asyncGlobleQueue
213 {
214     NSLog(@"asyncGlobleQueue-----begin");
215     //获得全局并发队列
216     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
217     //将 任务 添加到 全局并发队列 中去 异步执行-开线程
218     dispatch_async(queue, ^{
219         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
220     });
221     dispatch_async(queue, ^{
222         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
223     });
224     dispatch_async(queue, ^{
225         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
226     });
227     dispatch_async(queue, ^{
228         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
229     });
230     NSLog(@"asyncGlobleQueue-----end");
231 
232 
233 }
234 
235 /**
236  * async(异步) --串行队列(有时用)
237  * 会不会创建线程:会,创建一条
238  * 线程的执行方法:串行(一个任务执行完毕后,再执行下一个任务)
239  */
240 - (void)asyncSerialQueue
241 {
242     NSLog(@"asyncSerialQueue-----begin");
243     
244     //创建串行队列
245     dispatch_queue_t queue = dispatch_queue_create("cn.bowen.queue", NULL);
246     
247     //将 任务 添加到 串行队列 中去 异步执行-开线程
248     dispatch_async(queue, ^{
249         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
250     });
251     dispatch_async(queue, ^{
252         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
253     });
254     dispatch_async(queue, ^{
255         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
256     });
257     dispatch_async(queue, ^{
258         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
259     });
260     NSLog(@"asyncSerialQueue-----end");
261     
262     //非ARC需要手动释放串行队列
263     //dispatch_release(queue);
264 }
265 
266 
267 /**
268  * async(异步) --主队列(很常用)(特殊)
269  * 会不会创建线程:不会
270  * 任务的执行方式:串行
271  * 一般用在线程之间的通讯
272  */
273 - (void)asyncMainQueue
274 {
275     NSLog(@"asyncMainQueue-------begin");
276     //主队列(添加到主队列中的任务,自动放到主线程中执行)
277     dispatch_queue_t queue = dispatch_get_main_queue();
278     //将 任务 添加到 主队列 中去 异步执行(异步失效)
279     dispatch_async(queue, ^{
280         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
281     });
282     dispatch_async(queue, ^{
283         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
284     });
285     dispatch_async(queue, ^{
286         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
287     });
288     dispatch_async(queue, ^{
289         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
290     });
291     NSLog(@"asyncMainQueue-------end");
292 
293     
294 }
295 
296 #pragma mark - 同步
297 /**
298  * sync(同步) --主队列(不能用)
299  */
300 - (void)syncMainQueue
301 {
302     NSLog(@"syncMainQueue-------begin");
303     //主队列(添加到主队列中的任务,自动放到主线程中执行)
304     dispatch_queue_t queue = dispatch_get_main_queue();
305     //将 任务 添加到 主队列 中去 异步执行(异步失效)
306     dispatch_sync(queue, ^{
307         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
308     });
309     dispatch_sync(queue, ^{
310         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
311     });
312     dispatch_sync(queue, ^{
313         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
314     });
315     dispatch_sync(queue, ^{
316         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
317     });
318     NSLog(@"syncMainQueue-------end");
319 
320 }
321 
322 /**
323  * sync(同步) --并发队列
324  * 会不会创建线程:不会,在主线程中运行
325  * 任务的执行方式:串行(一个任务执行完毕后,再执行下一个任务)
326  * 并发队列失去并发功能
327  */
328 - (void)syncGlobleQueue
329 {
330     NSLog(@"syncGlobleQueue----begin");
331     //获得全局并发队列
332     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
333     //将 任务 添加到 全局并发队列 中去 同步执行
334     dispatch_sync(queue, ^{
335         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
336     });
337     dispatch_sync(queue, ^{
338         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
339     });
340     dispatch_sync(queue, ^{
341         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
342     });
343     dispatch_sync(queue, ^{
344         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
345     });
346     NSLog(@"syncGlobleQueue----end");
347 
348     
349 }
350 /**
351  * sync(同步) --串行队列
352  * 会不会创建线程:不会
353  * 线程的执行方法:串行(一个任务执行完毕后,再执行下一个任务)
354  */
355 - (void)syncSerialQueue
356 {
357     NSLog(@"syncSerialQueue----begin");
358     //创建串行队列
359     dispatch_queue_t queue = dispatch_queue_create("cn.bowen.queue", NULL);
360     
361     //将 任务 添加到 串行队列 中去 同步执行
362     dispatch_sync(queue, ^{
363         NSLog(@"\n----下载图片1----%@",[NSThread currentThread]);
364     });
365     dispatch_sync(queue, ^{
366         NSLog(@"\n----下载图片2----%@",[NSThread currentThread]);
367     });
368     dispatch_sync(queue, ^{
369         NSLog(@"\n----下载图片3----%@",[NSThread currentThread]);
370     });
371     dispatch_sync(queue, ^{
372         NSLog(@"\n----下载图片4----%@",[NSThread currentThread]);
373     });
374     NSLog(@"syncSerialQueue----end");
375 
376 }
377 
378 
379 #pragma mark - GCD基本使用
380 - (void)basicUse
381 {
382     //获得全局并发队列
383     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
384     //将任务添加到全局队列中去异步执行-开线程
385     dispatch_async(queue, ^{
386         NSLog(@"\n----下载图片----%@",[NSThread currentThread]);
387     });
388     
389     //在当前(并发)队列中执行同步执行-不开线程
390     dispatch_sync(queue, ^{
391         NSLog(@"\n----下载图片----%@",[NSThread currentThread]);
392     });
393     
394 }
395 
396 @end

 

IOS-线程(GCD)

原文:http://www.cnblogs.com/oc-bowen/p/5137635.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!