iOS GCD dispatch_async 多线程

来源:互联网 发布:中文数据库 编辑:程序博客网 时间:2024/05/01 18:57

多线程、推送消息、数据库,这三个方面,一直是我的难点。因为平时用不到,也没有去克服,现在应该好好地整整,逐一去克服了。


GCD的全称是:Grand Central Dispatch  中文翻译不知道。。。

意思为 用新的方法来进行并发程序的编写。允许将任务划分为多个单一任务,然后提交至工作队列来并发或者串行地执行。


除了代码的平行执行能力,GCD还提供高度集成的事件控制系统。可以设置句柄来响应文件描述符、mach ports(用于OS X上的进程间通讯)、进程、计时器、信号、用户生成事件。这些句柄通过GCD来并发执行。


GCD的API很大程度上基于block,所以GCD非常简单易用且能发挥其最大能力。


Dispatch Queues

GCD的基本概念就是dispatch queue。它是一个对象,可以接受任务,并将任务以先到先执行的顺序来执行。可以是并发或者串发。


GCD有三种队列类型:

1.The main queue:与主线程功能相同,会在主线程中执行。可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是个串行队列。

2.Global queue:全局队列是并发队列,并由整个进程共享,分高、中、低三个优先级。可以调用dispatch_get_global_queue函数传入优先级来访问队列,里面有优先级的设置,通过设置数字来设定优先级。。

3.用户队列:是用dispatch_queue_create创建的队列。是串行的,来完成同步机制,有点像mutex。eg:

dispatch_queue_t queue = dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>);

第一个参数,是用来标记队列的。第二个,可以传入NULL或者

DISPATCH_QUEUE_CONCURRENT


提交JOB


向一个队列提交Job很简单,调用dispatch_async函数,传入一个队列或者block,队列会在轮到这个block执行时执行这个block的代码。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        NSLog(@"kkkk");    });
dispatch_async 函数会立即返回,block会在后台异步执行。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        dispatch_async(dispatch_get_main_queue(), ^{            NSLog(@"main");        });    });

将要最后完成的内容,放在main函数里面。在外层执行后台任务,在嵌套的main函数完成主线程要完成的东西。


还有一个函数叫dispatch_sync,它干的事儿和dispatch_async相同,但是它会等待block中的代码执行完成并返回。结合 __block类型修饰符,可以用来从执行中的block获取一个值。例如,你可能有一段代码在后台执行,而它需要从界面控制层获取一个值。那么你可以使用dispatch_sync简单办到:

  1. - (id)something 
  2.     __block id localSomething; 
  3.     dispatch_sync(queue, ^{ 
  4.         localSomething = [something retain]; 
  5.     }); 
  6.     return [localSomething autorelease]; 
  7.  
  8. - (void)setSomething:(id)newSomething 
  9.     dispatch_async(queue, ^{ 
  10.         if(newSomething != something) 
  11.         { 
  12.             [something release]; 
  13.             something = [newSomething retain]; 
  14.             [self updateSomethingCaches]; 
  15.         } 
  16.     }); 

值得注意的是dispatch queue是非常轻量级的,所以你可以大用特用,就像你以前使用lock一样。

现在你可能要问:“这样很好,但是有意思吗?我就是换了点代码办到了同一件事儿。”

实际上,使用GCD途径有几个好处:

  1. 平行计算: 注意在第二个版本的代码中, -setSomething:是怎么使用dispatch_async的。调用 -setSomething:会立即返回,然后这一大堆工作会在后台执行。如果updateSomethingCaches是一个很费时费力的任务,且调用者将要进行一项处理器高负荷任务,那么这样做会很棒。
  2. 安全: 使用GCD,我们就不可能意外写出具有不成对Lock的代码。在常规Lock代码中,我们很可能在解锁之前让代码返回了。使用GCD,队列通常持续运行,你必将归还控制权。
  3. 控制: 使用GCD我们可以挂起和恢复dispatch queue,而这是基于锁的方法所不能实现的。我们还可以将一个用户队列指向另一个dspatch queue,使得这个用户队列继承那个dispatch queue的属性。使用这种方法,队列的优先级可以被调整——通过将该队列指向一个不同的全局队列,若有必要的话,这个队列甚至可以被用来在主线程上执行代码。
  4. 集成: GCD的事件系统与dispatch queue相集成。对象需要使用的任何事件或者计时器都可以从该对象的队列中指向,使得这些句柄可以自动在该队列上执行,从而使得句柄可以与对象自动同步。

总结

现在你已经知道了GCD的基本概念、怎样创建dispatch queue、怎样提交Job至dispatch queue以及怎样将队列用作线程同步。接下来我会向你展示如何使用GCD来编写平行执行代码来充分利用多核系统的性能^ ^。我还会讨论GCD更深层的东西,包括事件系统和queue targeting。



0 0
原创粉丝点击