您的位置:首页 > 移动开发 > IOS开发

IOS开中GCD相关

2014-03-14 01:00 375 查看
/*

 

 

// 定义Category类目扩展 DispatchLoad

@interface UIImageView (DispatchLoad)

- (void) setImageFromUrl:(NSString*)urlString;

- (void) setImageFromUrl:(NSString*)urlString completion:(void (^)(void))completion;

@end

 #import "UIImageView+DispatchLoad.h"

@implementation UIImageView (DispatchLoad)

 - (void) setImageFromUrl:(NSString*)urlString {

         [self setImageFromUrl:urlString completion:NULL];

     }

 - (void) setImageFromUrl:(NSString*)urlString

               completion:(void (^)(void))completion {

         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{

        

                 NSLog(@"Starting: %@", urlString);

                 UIImage *avatarImage = nil;

                 NSURL *url = [NSURL URLWithString:urlString];

                 NSData *responseData = [NSData dataWithContentsOfURL:url];

                 avatarImage = [UIImage imageWithData:responseData];

                 NSLog(@"Finishing: %@", urlString);

        

                 if (avatarImage) {

                         dispatch_async(dispatch_get_main_queue(), ^{

                                 self.image = avatarImage;

                             });

                         dispatch_async(dispatch_get_main_queue(), completion);

                     }

                 else {

                         NSLog(@"-- impossible download: %@", urlString);

                     }

             });

     }

@end

     一、GCD是异步执行任务的技术之一,一般将应用程序中记叙的线程管理用的代码在系统级中是实现。

         开发者只需要定义想要执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线

        程并计划执行任务。

 

 

     二、多线程编程

         由于使用多线程的程序可以在某个线程和其他线程之间反复多次进行上下文切换,因此看上去就好像

         一个CPU核能够并行的执行多个线程一样,而且在具有多个CPU核的情况下,就不是“看上去像”了,

         而是真的提供了多个CPU核并行执行任务的多个线程的技术。

 

        多线程编程容易发生各种编程问题:比如多个线程更新相同的资源会导致数据的不一致(数据竞争)、

        停止等待事件的线程会导致多个线程相互持续等待(死锁)、使用太多线程会消耗大量的内存资源等等。

        

        尽管会有问题,但是为什么还要用呢?

     

        在应用程序启动时,通过最先执行的线程,即主线程来描绘用户界面、处理用户触摸事件等,但是如果在

        该主线程中进行长时间的处理,就会妨碍主线程中被称为RunLoop的主循环的执行,从而导致不能跟新用

        户界面,应用程序的画面长时间停滞等问题。

 

 

 

     三、GCD
的 API

         1.Dispatch Queue

              开发者要做的只是定义想要执行的任务并追加到适当的DispatchQueue中。

              在Block中定义想要执行的任务,然后追加到Dispatch Queue中

              Dispatch Queue是执行处理的等待队列,通过dispatch_async等API,在Block语法中记叙想 

              要执行的处理并将其追加到Dispatch Queue中,Dispatch Queue按照追加的顺序(FIFO)执行处理。

              另外,在执行处理时存在两种Dispatch Queue:

          

              Dispatch Queue的种类说明:

         

              <A>/Serial Dispatch Queue 
等待现在执行中处理结束

 

              <B>/Concurrent Dispatch Queue
不等待现在执行中处理结束

 

 

 

    解释说明一下:

         (1)         

             Serial Dispatch Queue:就是要等待现在执行中处理结束后才可以进行下一个任务的执行处理,假如现在

             有blk1,blk2,blk3,在Serial Dispatch Queue中,那么同时执行处理数只能是一个,而且按按添加顺

             序FIFO进行处理,即先执行blk1,执行结束后再执行blk2,执行结束再进行blk3的执行。

         (2)         

             Concurrent Dispatch Queue:就是一个线程的执行不等待现在(当前)执行中的任务处理结束就可以开始

             另一个任务的执行处理。同样假如有blk1,blk2,blk3在Concurrent Dispatch
Queue中,那么首先执行

             blk1,不管blk1是否执行处理结束,都开始执行后面的blk2,不管blk2是否执行结束,都开始执行后面的blk2。

             这样虽然不用等待处理结束,可以并行执行多个任务处理,但是并行处理数取决于当前系统的状态,

                               有它决定Concurrent Dispatch Queue中并行执行的处理数。所谓并行执行就是使用多个线程来同时执行多个

                             处理任务(block中的执行任务)。

         

 

             SerialDispatchQueue同时只能执行一个追加处理

             ConcurrentDispatchQueue并行执行多个追加处理

             虽然SerialDispatchQueue ConcurrentDispatchQueue受到系统资源的限制,但是用

             dispatch_queue_create可以生成任意多个Dispatch Queue

             当生成多个SerialDispatchQueue时,各个SerialDispatchQueue将并行执行,虽然一个

             SerialDispatchQueue同时只能执行一个追加处理,但是如果将处理分别追加到4个

             Serial Dispatch Queue中,各个Serial Dispatch Queue执行一个,即为同时执行4个处理

             但是生成Serial Dispatch Queue的个数受系统限制

             

             为了避免多线程编程的问题之一---数据竞争,就可以使用Serial Dispatch Queue。

             当想并行执行且不发生数据竞争等问题时就应该使用Concurrent Dispatch Queue。

 

 [cpp]

             //以下代码是两种生成Serial Dispatch Queue的方式

             dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", NULL);

             //        dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);

             //以下代码是两种生成Serial Dispatch Queue的方式

             dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", NULL);

             //        dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);

             

             

             dispatch_queue_create,该方法中的第一个参数指定SerialDispatchQueue的名称,

             DispatchQueue的名称推荐使用应用程序ID之中逆序全程域名,第二个参数指定为NULL

                          (或DISPATCH_QUEUE_SERIAL)时即表示生成的是Serial Dispatch Queue,指定为

              DISPATCH_QUEUE_CONCURRENT时即表示生成的是Concurrent Dispatch Queue

 

 

 */

             dispatch_queue、dispatch_group、dispatch_semaphore dispatch_queue、

     

             //attr DISPATCH_QUEUE_CONCURRENT:创建并行queue,iOS5和OSX7以后支持该特性;

             //DISPATCH_QUEUE_SERIAL:创建串行queue,默认值为NULL。

             dispatch_queue_create(const char *queue_label, dispatch_queue_attr attr)

             

             //在不阻塞当前线程的情况下,将 block
提交到 queue
上异步执行。

             void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

             

             //与上面相反,等 block
执行完后,当前线程继续执行后续工作。

             void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

             

             dispatch_group

             

             //以下为伪代码,不可执行,用以说明问题

             //将 block1, block2
分别提交到各自的 dispatch_queue
(也可以为同一个diaptch_queue)上异步执行。

             dispatch_group_async(dispatch_group_t group1,

             dispatch_queue_t queue1,

             dispatch_block_t block1);

             

             dispatch_group_async(dispatch_group_t group,

             dispatch_queue_t queue2,

             dispatch_block_t block2);

             

             //等待直到 group1
中的任务数降为0再继续后面的代码。其中超时参数代表等待超时的长短,如果超时,

             //则直接往后执行。(DISPATCH_TIME_FOREVER:值为~0ull。 DISPATCH_TIME_NOW:值为0。)

             dispatch_group_wait(dispatch_group_t group1, dispatch_time_t timeout);

             

             dispatch_group_async(dispatch_group_t group1,

             dispatch_queue_t queue1,

             dispatch_block_t block1);

             

             //其实,dispatch_group
的作用就是将提交到 dispatch_queue
上的 block 进行分组,以

             //dispatch_group_wait 函数为分界线,然后以组为单位进行组内的任务调度工作。

             //一切都是以 block
为最基本的任务单元来操作。

     

             dispatch_semaphore

             信号量用来控制线程间同步操作,一般流程是,需要同步的代码,在执行前发送等待信号,锁住该段代码的入口,

             执行完毕后发送信号通知解锁。其他线程也同样。具体代码如下:

     

             static dispatch_once_t onceToken;

             dispatch_once(&amp;onceToken, ^{

             if (!_hasRan) {

             hugeComputing();

             _hasRan = YES;

             NSLog(@&quot;%s  HasRun!&quot;, __FUNCTION__);

             }

             });

             

             

             dispatch_suspend 和 dispatch_resume

             这两个函数作用是在 dispatch_queue
的 block
单元之间进行暂停和恢复的操作,因此,在一个

             block 执行完毕之前,该 dispatch_queue
是不会暂停的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: