谈谈关于GCD相关问题

记录下关于学习和使用GCD的一些问题和理解。

GCD,Grand Central Dispatch的简称。首次发布在Mac OS X 10.6 ,iOS 4开始引入使用,是以纯C为底层的强大技术。其操作机制是基于线程上队列对于任务的调度执行,遵循FIFO(First In First Out)。

对于线程常用的三个方式的比较:

 NSThead主要做简单的,缺点是无法管理线程的数量,需要手动管理线程。

// 开启并且执行一个线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

// 创建一个线程但是不会执行,需要手动调用
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(id)argument 

// 通过通知中心监听此消息达到监听线程结束的目的
NSThreadWillExitNotification

NSOperation是基于OC的面向对象的多线程可以管理线程数,比GCD多了一些简单实用的功能。

//  maxConcurrentOperationCount
设置最大开启的线程数,设置为1,则成为串行队列,否则,为并发队列

GCD是基于C的,效率高,会自动的管理线程周期(包括创建线程,任务处理,销毁线程)。

注意一个技巧:三种线程方式,都可以使用[NSThread currentThread]追踪任务所在的线程。


下面我们主要看下GCD的核心三个方面:线程、 队列 、任务(block执行块)。原理是将一段(Block)代码作为特定任务,放到指定的队列(queue:Serial(串行,同时只能执行一个任务)/globel(并行,同时可执行多个任务,但执行顺序是随机的)/main(全局的Serial,在主线程里面执行任务) dispatch queue)里,进行同步/异步(dispatch_sync/dispatch_async)处理。根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。其中 线程分为:主线程、分线程(子线程)

 队列分为:

(1)串行队列:自己手动创建的,队列中的任务只会顺序执行  (类似排队)(DISPATCH_QUEUE_SERIAL也可使用NULL代替)。

  dispatch_queue_t q = dispatch_queue_create(“....”, DISPATCH_QUEUE_SERIAL);

 (2)并行队列自己手动创建的,队列中的任务通常会并发执行(类似赛跑)

     dispatch_queue_t q = dispatch_queue_create("......", DISPATCH_QUEUE_CONCURRENT);

  ( 3)系统提供的几个并发队列。他们叫做全局调度队列(Global Dispatch Queues) ,一般进程中存在三个全局队列。全局队列有着依次从低到高的四个不同优先级:backgroundlowdefault 以及 high。PS:Apple 的 API 也会使用这些队列,所以你添加的任何任务都不会是这些队列中唯一的任务。

      dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

(4)  主队列,提交至main queue的任务会在主线程中执行,是一个默认的串行队列。

            dispatch_queue_t q = dispatch_get_main_queue();

处理线程中的队列任务,我们需要记得两句话:同步异步(dispatch_sync/dispatch_async)决定开不开线程,串行并行决定开几条线程。

关于我们在实际开发中,利用GCD去做一些线程处理时,常用方法有下面几种简单的使用:

// 异步执行:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// something
});

// 主线程执行:
dispatch_async(dispatch_get_main_queue(), ^{
// something
});

// 一次性执行:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});

// 延迟2秒执行:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
});

// 自定义dispatch_queue_t
dispatch_queue_t  urls_queue = dispatch_queue_create("blog.LL86.com", NULL);
dispatch_async(urls_queue, ^{ 
   // your code 
});
dispatch_release(urls_queue);

// 快速迭代遍历
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
    // 执行10次代码,index顺序不确定
});

//常用结构
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
    // 耗时的操作  
    dispatch_async(dispatch_get_main_queue(), ^{  
        // 主线程刷新UI  
    });  
});  

dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行1个耗时的异步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行1个耗时的异步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的异步操作都执行完毕后,回到主线程...
});
其中需要注意的是:

dispatch_after  是 延迟提交任务,并不是延迟多少秒后立即执行。在使用GCD做定时源时,使用dispatch_source_create创建一个定时器并绑定到主分派队列上。GCD定时器是基于分派队列,而不是像NSTimer那样基于运行循环,这意味着把他们用在多线程应用中要容易的多。

dispatch_suspend(queue)   挂起队列,并不是立即暂停正在运行的block任务,而是在当前block任务执行结束以后,暂停后续的block运行。\-。-/~

dispatch_sync  都不陌生的是,这句代码本身就是要放入主线程中运行的,因此有时不注意的一些操作会常造成我们常说的死锁现象(也就是线程相互等待现象)。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值