网络与多线程---OC中多线程方法GCD(二)

小编在前一篇中介绍了多线程实现的五种常用方法。在接下来所介绍的这种方法是最具有魅力的,最具有诱惑的实现多线程的方案---GCD

一、什么是GCD

  GCD是Grand Central Dispatch的简称,是基于C语言的。如果使用GCD,完全由系统管理线程,我们不需要编写线程代码。只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue)。GCD会负责创建线程和调度你的任务,系统直接提供线程管理,大大的提高代码的执行效率与多核的利用率。
1.GCD的一个重要概念是队列,它的核心理念:将长期运行的任务拆分成多个工作单元,并将这些单元添加到dispath queue中,系统会为我们管理这些dispath queue,为我们在多个线程上执行工作单元,我们不需要直接启动和管理后台线程。

2.系统提供了许多预定义的dispath queue,包括可以保证始终在主线程上执行工作的dispath queue。也可以创建自己的dispath queue,而且可以创建任意多个。GCD的dispath queue严格遵循FIFO(先进先出)原则,添加到dispath queue的工作单元将始终按照加入dispath queue的顺序启动。

3.dispatch queue按先进先出的顺序,串行或并发地执行任务

二、创建和管理GCD

   并发dispatch queue可以同时并行地执行多个任务,不过并发queue仍然按先进先出的顺序来启动任务。并发queue会在之前的任务完成之前就出列下一个任务并开始执行。并发queue同时执行的任务数量会根据应用和系统动态变化,各种因素包括:可用核数量、其它进程正在执行的工作数量、其它串行dispatch queue中优先任务的数量等.

 1 //创建一个队列
 2     dispatch_queue_attr_t queue =  dispatch_queue_create("test", NULL);
 3 /********此种方式是异步多线程的运行*********/
 4     dispatch_async(queue, ^{
 5         for (int i = 0; i < 100; i++) {
 6             NSLog(@"---这是多线程---%d",i);
 7         }
 8         
 9         //回到主线程
10         dispatch_sync(dispatch_get_main_queue(), ^{
11             BOOL isMain = [NSThread isMainThread];
12             if (isMain) {
13                 NSLog(@"isMain");
14             }
15         });
16     });
17 
18 /********此种方式是同步多线程的运行*********/
19 dispatch_sync(queue, ^{
20         //demo
21     });


  GCD提供了函数让应用访问几个公共dispatch queue:

1> 使用dispatch_get_current_queue函数作为调试用途,或者测试当前queue的标识。在block对象中调用这个函数会返回 block提交到的queue(这个时候queue应该正在执行中)。在block对象之外调用这个函数会返回应用的默认并发queue。
2> 使用dispatch_get_main_queue函数获得应用主线程关联的串行dispatch queue

备注:在新创建的子线程中,需要添加自动释放池来管理内存。
  GCD支持Cocoa内存管理机制,因此可以在提交到queue的 block中自由地使用Objective-C对象。每个dispatch queue维护自己的autorelease pool确保释放autorelease对象,但是queue不保证这些对象实际释放的时间。如果应用消耗大量内存,并且创建大量autorelease 对象,你需要创建自己的autorelease pool,用来及时地释放不再使用的对象。

三、暂停和继续queue

  我们可以使用dispatch_suspend函数暂 停一个queue以阻止它执行block对象;使用dispatch_resume函数继续dispatch queue。调用dispatch_suspend会增加queue的引用计数,调用dispatch_resume则减少queue的引用计数。当引用 计数大于0时,queue就保持挂起状态。因此你必须对应地调用suspend和resume函数。挂起和继续是异步的,而且只在执行block之间(比 如在执行一个新的block之前或之后)生效。挂起一个queue不会导致正在执行的block停止。

四、案例

  小编通过使用GCD的实现方法,通过URL来异步存储图片。

 1 @implementation UIImageView (webCach)
 2 - (void)setUIImageWithUrl:(NSURL*)url
 3 {
 4     //使用异步线程来下载
 5     dispatch_queue_t  queue = dispatch_queue_create("imageLoad", NULL);
 6     dispatch_async(queue, ^{
 7         NSData *data = [NSData dataWithContentsOfURL:url];
 8         UIImage *image = [UIImage imageWithData:data];
 9         //主线程
10         dispatch_sync(dispatch_get_main_queue(), ^{
11             self.image = image;
12         });
13     });
14 
15 }
16 @end

 

1 - (void)viewDidLoad {
2     
3     [super viewDidLoad];
4     
5     UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 500)];
6     [imageView setUIImageWithUrl:[NSURL URLWithString:@"http://s1.dwstatic.com/group1/M00/F5/00/f251b9aca3b84a55449f1083e9fe8cda.jpg"]];
7     [self.view addSubview:imageView];
8     
9 }

   当图片异步加载完成后,就会展现出来。但是,第二次进入该界面,还是要重新下载图片,用户体验不好,且浪费资源(比如耗电)。

   于是,考虑缓存已经下载的图片。

 

小便的能力有限,欢迎大牛指正!!!

posted on 2015-05-08 22:56  bob-tong  阅读(278)  评论(0编辑  收藏  举报

导航