GCD理解(二)

串行

串行队列包括用户队列、主线程队列

-串行同步

  //串行同步
 dispatch_queue_t queue = dispatch_queue_create("serial_sync", nil);
    dispatch_sync(queue, ^{
        sleep(1);
        NSLog(@"sync serial name '%@' in a process",queue);
    });
    NSLog(@"sync serial sync process end");

- 串行异步

//串行异步
    dispatch_queue_t asynQueue = dispatch_queue_create("serial_async", nil);
    dispatch_async(asynQueue, ^{
        sleep(1);
        NSLog(@"async serial name '%s' in a process",dispatch_queue_get_label(asynQueue));
    });
    NSLog(@"async serial sync process end");

并行

    //并发队列 :Concurrent Queues
    dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t aHQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_queue_t aLQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

Demo-并行队列

- (void)testConcurrentQueue{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //记时开始
    NSDate *startTime = [NSDate date];
    //两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.
    //加入队列
    dispatch_async(concurrentQueue, ^{
        NSLog(@"并行同步 start at %@",startTime);
        __block UIImage *image = nil;

        //1.先去下载图片
        dispatch_sync(concurrentQueue, ^{
            NSString *urlAsString = @"https://www.baidu.com/img/bdlogo.png";
            NSURL *url = [NSURL URLWithString:urlAsString];

            NSError *downloadError = nil;

            NSData *imageData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:&downloadError];

            if (downloadError == nil && imageData != nil) {
                image = [UIImage imageWithData:imageData];
            }
            else if(downloadError != nil){
                NSLog(@"error happened = %@", downloadError);
            }
            else{
                NSLog(@"No data download");
            }
        });

        //2.在主线程展示到界面里
        __block typeof (self)weakSelf = self;

        dispatch_sync(dispatch_get_main_queue(), ^{
            if (image != nil) {
                [weakSelf.imageView setImage:image];
                NSDate *endTime = [NSDate date];
                NSLog(@"并行同步 completed in %f time", [endTime timeIntervalSinceDate:startTime]);
            }
            else{
                NSLog(@"image isn't downloaded, nothing to display");
            }
        });
    });

}

主队列

    //主队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

分组

对分组的理解

将几个有关联的任务组合起来,然后提供一个知道这个group结束的点,接着再执行其他任务。
dispatch_notify()提供了一个知道group什么时候结束的点. 也可以使用dispatch_wait()去阻塞.见demo

Demo-简单分组

 //获取并发队列:加上sleep可以更好的理解
    dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //创建2个queue group: a 负责任务123,b负责456
    dispatch_group_t aGroup = dispatch_group_create();
    dispatch_group_t bGroup = dispatch_group_create();

    dispatch_group_async(aGroup, aQueue, ^{
        NSLog(@"task 1 start");
        sleep(3);
        NSLog(@"task 1 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));

    });
    dispatch_group_async(aGroup, aQueue, ^{
        NSLog(@"task 2 start");
        sleep(2);
        NSLog(@"task 2 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));

    });
    dispatch_group_async(aGroup, aQueue, ^{
        NSLog(@"task 3 start");
        sleep(10);
        NSLog(@"task 3 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));

    });
    NSLog(@"wait task 1,2,3.");
    //等待组内任务全部完成
    dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER);
    NSLog(@"task 1,2,3 finished.");

    //任务4
    dispatch_group_async(bGroup, aQueue, ^{
        NSLog(@"task 4.");
    });
    //任务5
    dispatch_group_async(bGroup, aQueue, ^{
        NSLog(@"task 5.");
    });
    //任务6
    dispatch_group_async(bGroup, aQueue, ^{
        NSLog(@"task 6.");
    });
    NSLog(@"wait task 4,5,6.");
    //等待组内任务全部完成
    dispatch_group_wait(bGroup, DISPATCH_TIME_FOREVER);
    NSLog(@"task 4,5,6 finished.");

分组的例子:下载图片并展示

  dispatch_group_t group = dispatch_group_create();

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    NSDate *startTime = [NSDate date];

    __block UIImage *image = nil;

    dispatch_group_async(group, queue, ^{
        NSLog(@"分组同步 start in %@",startTime);
        //1.先去网上下载图片
        NSString *urlAsString = @"http://s0.hao123img.com/res/img/logo/logonew1.png";
        NSURL *url = [NSURL URLWithString:urlAsString];

        NSError *downloadError = nil;

        NSData *imageData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:&downloadError];

        if (downloadError == nil && imageData != nil) {
            image = [UIImage imageWithData:imageData];
        }
        else if(downloadError != nil){
            NSLog(@"error happened = %@", downloadError);
        }
        else{
            NSLog(@"No data download");
        }

    });
    __block typeof (self)weakSelf = self;

    // 2.等下载好了再在刷新主线程
    dispatch_group_notify(group, queue, ^{

        //在主线程展示到界面里
        dispatch_async(dispatch_get_main_queue(), ^{
            if (image != nil) {
                [weakSelf.imageView setImage:image];


                NSDate *endTime = [NSDate date];
                NSLog(@"分组同步 end at %@,completed in %f time",endTime, [endTime timeIntervalSinceDate:startTime]);
            }
            else{
                NSLog(@"image isn't downloaded, nothing to display");
            }
        });

    });

  • concurrent queues和main queue都是由系统生成而且 dispatch_suspend, dispatch_resume, dispatch_set_context这些函数对他们无效。
  • GCD下的dispatch_queue队列不管是并发队列都是FIFO队列,,都会按照提交到队列的顺序执行.
  • 提交到主线程队列的时候,要慎用dispatch_sync方法,有可能造成死锁. 因为主线程队列是串行队列,要等队列里的任务一个一个执行.所以提交一个任务到队列,如果用同步方法就会阻塞住主线程,而主线程又要等主线程队列里的任务都执行完才能执行刚提交的,所以主线程队列里还有其他的任务的话,但他已经被阻塞住了,没法先完成队列里的其他任务,即,最后一个任务也没机会执行到,于是造成死锁.
  • 提交到串行队列可以用同步方式,也可以用异步方式.
  • 采用并行队列的时候,可以采用同步的方式把任务提交到队列里去,即可以实现同步的方式(两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.)

如有不对,请指正。谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值