GCD队列
GCD队列
iossocket 发表于2年前
GCD队列
  • 发表于 2年前
  • 阅读 66
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 介绍GCD中常用的队列,体统所提供的队列和自定义队列。

Queues队列

    GCD提供了dispatch queues来处理我们提交给该该队列的任务,并使用了FIFO(先进先出)的方式来处理任务,可使第一个提交的任务第一个开始执行,第二个提交的任务,第二个开始执行,以此类推。串行和并发都是如此。

    队列可被分为串行队列和并发队列。其中串行队列,一次只执行一个任务,当此任务完成时,开始执行下一个任务;而并发队列,可实现多个任务同时在执行(此行为的实现方式也取决于CPU核数,对于单核CPU则是通过时间片的方式切换执行多任务)。

队列类型

    系统为我们提供了两种队列。其一,主队列,这是一种特殊的串行队列,此队列的任务均执行在主线程上,而主线程是唯一可更新UI的线程;其二,全局队列,它又可又优先级(backgroud、low、default、hight)的不同分为4种队列。系统也会使用这些队列,因此这些队列中也将会存在系统任务。

    另外,我们可以使用自定义队列,如何选择何时应选用这三种队列呢?

    主队列:当我们需要更新UI时,只能选用主队列。

    并发队列:当我们需要在后台执行一些和UI无关的工作时。 参考如下代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // do something which do not relate to UI
    dispatch_async(dispatch_get_main_queue(), ^{
        // do something related to UI
    });
});

    自定义队列:当我们想在后台执行一系列工作,并想要跟踪这些工作的状态时,应选用自定义串行队列,它可以有效避免资源争用。创建自定义队列时使用方法dispatch_queue_create方法,第一个参数为一个字符串,对该队列进行标示,第二个参数为该队列的类型可以指定为串行队列DISPATCH_QUEUE_SERIAL,或并发队列DISPATCH_QUEUE_CONCURRENT。当设置为NULL时默认为串行队列。

dispatch_queue_t myQueue = dispatch_queue_create("com.iossocket", NULL);

dispatch_async(myQueue, ^{
    // do something
})

dispatch_release(myQueue);

在我们创建队列时,为队列起一个具有标示意义的标签,可以方便我们的调试。

当iOS版本低于6.0时,需要自己管理GCD对象。当高于6.0时ARC已经替我们管理了GCD对象,无需手动release它。


dispatch方法

1. 异步后台执行异步队列

dispatch_async(dispatch_get_global_queue(0,0), ^{
    // do sth...
});

2. 异步执行UI操作

dispatch_async(dispatch_get_main_queue(), ^{
    // do sth...
});

3. 执行一次性任务,可在创建单例时使用。

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // this code just be executed once...
});

    当在单例中使用时:(要onceToken设置为static,或具有全局作用域)

+ (instancetype)single { 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
        single = [[MySingle alloc] init]; 
    }); 
    return single; 
}

4. 延时执行

double delayTime = 3.0;
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, delayTime * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^{
   // after 3 seconds, these code will be executed...
});

5. 重复任务

dispatch_apply(3, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
    sleep(5);
    NSLog(@"no..%zu", index);
});

使用dispatch_apply提交的任务,将阻塞主线程,既是被提交到全局并发队列中,通过上述代码的sleep(5)中可以发现。可通过如下方式来避免阻塞主线程:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_apply(3, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        sleep(5);
        NSLog(@"no..%zu", index);
    });
});

6. dispatch_group:当两个线程都执行完成后,在汇总结果。

dispatch_grout_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) ^{ 
    // do sth...            
});
        
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) ^{
    // do sth...         
});

dispatch_group_notify(group, dispatch_get_main_queue()) ^{
    // 该group中的任务都完成后,该block才会执行。
});

7. dispatch_suspend/dispatch_resume 暂停和恢复运行

dispatch_suspend(group);
dispatch_resume(group);

继上述6的group之后,我们再来看一下暂停线程组和恢复线程组运行的两个API,当执行suspend之后,并不会影响已经提交的任务执行,之后暂停在suspend的之后提交的任务。而resume的作用为恢复线程组,使其继续执行。





共有 人打赏支持
粉丝 5
博文 18
码字总数 8603
×
iossocket
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: