GCD理解(二)

来源:互联网 发布:怎么发送淘宝店铺链接 编辑:程序博客网 时间:2024/06/05 17:33

串行

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

-串行同步

  //串行同步 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方法,有可能造成死锁. 因为主线程队列是串行队列,要等队列里的任务一个一个执行.所以提交一个任务到队列,如果用同步方法就会阻塞住主线程,而主线程又要等主线程队列里的任务都执行完才能执行刚提交的,所以主线程队列里还有其他的任务的话,但他已经被阻塞住了,没法先完成队列里的其他任务,即,最后一个任务也没机会执行到,于是造成死锁.
  • 提交到串行队列可以用同步方式,也可以用异步方式.
  • 采用并行队列的时候,可以采用同步的方式把任务提交到队列里去,即可以实现同步的方式(两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.)

如有不对,请指正。谢谢

0 0
原创粉丝点击