GCD使用与技巧(续)

后台执行 , 前台执行

    // 前台执行
    dispatch_async(dispatch_get_main_queue(), ^{
        // do something
    });
    // 后台执行
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // do something 
       });

dispatch_once_t必须是全局或static变量 毕竟非全局或非static的dispatch_once_t变量在使用时会导致非常不好排查的bug

// 一次执行, 只执行一次
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 单例
    });

dispatch_queue_create,创建队列用的,它的参数只有两个, 而dispatch_queue_attr_t类型是有已经定义好的常量

// 串行
    dispatch_queue_t queueSerial     = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    // 并行
    dispatch_queue_t queueComcurrent = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);

dispatch_after

// 创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("myQueueSerial", DISPATCH_QUEUE_SERIAL);
    // 打印第一条数据
    NSLog(@"begin add block join in ...");
    // 提交一个block
    // 异步执行
    dispatch_async(queue, ^{
        // sleep 10s
        [NSThread sleepForTimeInterval:10];
        NSLog(@"sleep block done .... ");
    });
    // 5s 以后调教block
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"after block done ...");
    });
结果输出
2016-03-09 16:51:32.382 PopView[3310:237164] begin add block join in ...
2016-03-09 16:51:37.383 PopView[3310:237164] after block done ...
2016-03-09 16:51:42.383 PopView[3310:237293] sleep block done ....

dispatch_time_t正确创建姿势

用dispatch_after的时候就会用到dispatch_time_t变量, 如何创建合适的时间
/**
* @param when 第一个参数一般是 DISPATCH_TIME_NOW,表示从现在开始
* @param delta delta 纳秒
*/
* 延时一秒可以这样
* dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
* dispatch_time(DISPATCH_TIME_NOW, 1000 * USEC_PER_SEC);
* dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC * NSEC_PER_USEC); — 每秒的毫秒数乘以每毫秒的纳秒数

 //原型 
dispatch_time_t dispatch_time ( dispatch_time_t when, int64_t delta );

dispatch_suspend, dispatch_resume: 提供挂起、恢复”队列的功能

dispatch_queue_t queueTest = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL);
    //提交第一个block,延时5秒打印。
    dispatch_async(queueTest, ^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"After 5 seconds...");
    });
    //提交第二个block,也是延时5秒打印
    dispatch_async(queueTest, ^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"After 5 seconds again...");
    });
    //延时一秒
    NSLog(@"sleep 1 second...");
    [NSThread sleepForTimeInterval:1];
    //挂起队列
    NSLog(@"suspend...");
    dispatch_suspend(queueTest);
    //延时10秒
    [NSThread sleepForTimeInterval:10];
    NSLog(@"sleep 10 second...");
    //恢复队列
    dispatch_resume(queueTest);
    NSLog(@"resume...");
2016-03-09 17:11:19.401 PopView[3430:251221] sleep 1 second...
2016-03-09 17:11:20.402 PopView[3430:251221] suspend...
2016-03-09 17:11:24.405 PopView[3430:251253] After 5 seconds...
2016-03-09 17:11:30.404 PopView[3430:251221] sleep 10 second...
2016-03-09 17:11:30.404 PopView[3430:251221] resume...
2016-03-09 17:11:35.409 PopView[3430:251253] After 5 seconds again...

dispatch_apply

dispatch_queue_t queue = dispatch_queue_create("queue-", DISPATCH_QUEUE_SERIAL);
    // 执行5次
    dispatch_apply(3, queue, ^(size_t i) {
        NSLog(@"apply loop: %zu", i);
    });
    NSLog(@"after apply");
// 明明是异步, 却最后打印如下, dispatch_apply将外面的线程(main线程)“阻塞”了!
// 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 0
// 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 1
// 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 2
// 2016-03-09 17:19:32.628 PopView[3474:255956] after apply

出现死锁的情况

// 情况一
- (void)updateUI1 {
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"Update ui 1");

            //死锁!
            [self updateUI2];
        });
    }
    - (void)updateUI2 {
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"Update ui 2");
        });
    }
dispatch_queue_t queue11 = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL);
dispatch_apply(3, queue, ^(size_t i) {
        NSLog(@"apply loop: %zu", i);

        //再来一个dispatch_apply!死锁!
        dispatch_apply(3, queue, ^(size_t j) {
            NSLog(@"apply loop inside %zu", j);
        });
    });  // 这端代码只会输出“apply loop: 1”。。。就没有然后了 O.o --- 避免dispatch_apply的嵌套调用

dispatch_group_t

dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
       // Do your something
    });
// 当你无法直接使用队列变量时,就无法使用dispatch_group_async了,下面以使用AFNetworking时的情况:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    //Enter group
    dispatch_group_enter(group);
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        //Deal with result...
        //Leave group
        dispatch_group_leave(group);
    }    failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //Deal with error...
        //Leave group
        dispatch_group_leave(group);
    }];
    //More request... // 使用dispatch_group_enter,dispatch_group_leave就可以很方便处理

文章参照 : http://www.cocoachina.com/ios/20150505/11751.html

你可能感兴趣的:(gcd)