博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GCD
阅读量:6906 次
发布时间:2019-06-27

本文共 19400 字,大约阅读时间需要 64 分钟。

hot3.png

GCD的基础知识

 

 

 

同步函数+串行队列

//同步函数 + 串行队列- (void)syncSerial {        NSLog(@"start %s -------%@",__FUNCTION__,[NSThread currentThread]);    /* 创建串行队列 */    dispatch_queue_t queue = dispatch_queue_create("https://teilim.com", DISPATCH_QUEUE_SERIAL);        /* 将执行任务加入队列 */    dispatch_sync(queue, ^{        for (NSInteger i = 0; i<5; i++) {            NSLog(@"task A time %lo -----%@", i,[NSThread currentThread]);        }    });    dispatch_sync(queue, ^{        for (NSInteger i = 0; i<5; i++) {            NSLog(@"task B time %lo -----%@", i,[NSThread currentThread]);        }    });    NSLog(@"finish %s -------%@",__FUNCTION__,[NSThread currentThread]);}

打印内容

2016-11-11 20:16:47.338 MutipleThreadPractice[27817:3509801] start -[GCDDemoViewController syncSerial] -------
{number = 1, name = main}2016-11-11 20:16:47.339 MutipleThreadPractice[27817:3509801] task A time 0 -----
{number = 1, name = main}2016-11-11 20:16:47.339 MutipleThreadPractice[27817:3509801] task A time 1 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task A time 2 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task A time 3 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task A time 4 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task B time 0 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task B time 1 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task B time 2 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task B time 3 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] task B time 4 -----
{number = 1, name = main}2016-11-11 20:16:47.340 MutipleThreadPractice[27817:3509801] finish -[GCDDemoViewController syncSerial] -------
{number = 1, name = main}

 

同步函数+并发队列

//同步函数 + 并发队列- (void)syncConcurrent {        NSLog(@"start %s -------%@",__FUNCTION__,[NSThread currentThread]);    /* 创建并发队列 */    dispatch_queue_t queue = dispatch_queue_create("https://teilim.com", DISPATCH_QUEUE_CONCURRENT);        /* 将执行任务加入队列 */    dispatch_sync(queue, ^{        for (NSInteger i = 0; i<5; i++) {                NSLog(@"task A time %lo -----%@", i,[NSThread currentThread]);        }    });    dispatch_sync(queue, ^{        for (NSInteger i = 0; i<5; i++) {              NSLog(@"task B time %lo -----%@", i,[NSThread currentThread]);        }    });    NSLog(@"finish %s -------%@",__FUNCTION__,[NSThread currentThread]);}

 

打印内容

2016-11-11 20:19:35.113 MutipleThreadPractice[27817:3509801] start -[GCDDemoViewController syncConcurrent] -------
{number = 1, name = main}2016-11-11 20:19:35.113 MutipleThreadPractice[27817:3509801] task A time 0 -----
{number = 1, name = main}2016-11-11 20:19:35.114 MutipleThreadPractice[27817:3509801] task A time 1 -----
{number = 1, name = main}2016-11-11 20:19:35.114 MutipleThreadPractice[27817:3509801] task A time 2 -----
{number = 1, name = main}2016-11-11 20:19:35.114 MutipleThreadPractice[27817:3509801] task A time 3 -----
{number = 1, name = main}2016-11-11 20:19:35.115 MutipleThreadPractice[27817:3509801] task A time 4 -----
{number = 1, name = main}2016-11-11 20:19:35.115 MutipleThreadPractice[27817:3509801] task B time 0 -----
{number = 1, name = main}2016-11-11 20:19:35.115 MutipleThreadPractice[27817:3509801] task B time 1 -----
{number = 1, name = main}2016-11-11 20:19:35.117 MutipleThreadPractice[27817:3509801] task B time 2 -----
{number = 1, name = main}2016-11-11 20:19:35.117 MutipleThreadPractice[27817:3509801] task B time 3 -----
{number = 1, name = main}2016-11-11 20:19:35.117 MutipleThreadPractice[27817:3509801] task B time 4 -----
{number = 1, name = main}2016-11-11 20:19:35.118 MutipleThreadPractice[27817:3509801] finish -[GCDDemoViewController syncConcurrent] -------
{number = 1, name = main}

 

异步函数+串行队列

//异步函数 + 串行队列- (void)asyncSerial {        NSLog(@"start %s -------%@",__FUNCTION__,[NSThread currentThread]);        /* 创建串行队列 */    dispatch_queue_t queue = dispatch_queue_create("https://teilim.com", DISPATCH_QUEUE_SERIAL);        /* 将任务加入队列 */    dispatch_async(queue, ^{        for (NSInteger i = 0; i<5; i++) {            NSLog(@"task A time %lo -----%@", i,[NSThread currentThread]);        }    });    dispatch_async(queue, ^{        for (NSInteger i = 0; i<5; i++) {              NSLog(@"task B time %lo -----%@", i,[NSThread currentThread]);        }    });        NSLog(@"finish %s -------%@",__FUNCTION__,[NSThread currentThread]);}

 

打印内容

2016-11-11 20:20:58.620 MutipleThreadPractice[27817:3509801] start -[GCDDemoViewController asyncSerial] -------
{number = 1, name = main}2016-11-11 20:20:58.621 MutipleThreadPractice[27817:3509801] finish -[GCDDemoViewController asyncSerial] -------
{number = 1, name = main}2016-11-11 20:20:58.621 MutipleThreadPractice[27817:3515050] task A time 0 -----
{number = 2, name = (null)}2016-11-11 20:20:58.622 MutipleThreadPractice[27817:3515050] task A time 1 -----
{number = 2, name = (null)}2016-11-11 20:20:58.623 MutipleThreadPractice[27817:3515050] task A time 2 -----
{number = 2, name = (null)}2016-11-11 20:20:58.624 MutipleThreadPractice[27817:3515050] task A time 3 -----
{number = 2, name = (null)}2016-11-11 20:20:58.626 MutipleThreadPractice[27817:3515050] task A time 4 -----
{number = 2, name = (null)}2016-11-11 20:20:58.626 MutipleThreadPractice[27817:3515050] task B time 0 -----
{number = 2, name = (null)}2016-11-11 20:20:58.627 MutipleThreadPractice[27817:3515050] task B time 1 -----
{number = 2, name = (null)}2016-11-11 20:20:58.627 MutipleThreadPractice[27817:3515050] task B time 2 -----
{number = 2, name = (null)}2016-11-11 20:20:58.627 MutipleThreadPractice[27817:3515050] task B time 3 -----
{number = 2, name = (null)}2016-11-11 20:20:58.628 MutipleThreadPractice[27817:3515050] task B time 4 -----
{number = 2, name = (null)}

 

 

异步函数+并发队列

//异步函数 + 串行队列- (void)asyncSerial {        NSLog(@"start %s -------%@",__FUNCTION__,[NSThread currentThread]);        /* 创建串行队列 */    dispatch_queue_t queue = dispatch_queue_create("https://teilim.com", DISPATCH_QUEUE_SERIAL);        /* 将任务加入队列 */    dispatch_async(queue, ^{        for (NSInteger i = 0; i<5; i++) {            NSLog(@"task A time %lo -----%@", i,[NSThread currentThread]);        }    });    dispatch_async(queue, ^{        for (NSInteger i = 0; i<5; i++) {              NSLog(@"task B time %lo -----%@", i,[NSThread currentThread]);        }    });        NSLog(@"finish %s -------%@",__FUNCTION__,[NSThread currentThread]);}

 

 

打印内容

2016-11-11 20:22:17.234 MutipleThreadPractice[27817:3509801] start -[GCDDemoViewController asyncConcurrent] -------
{number = 1, name = main}2016-11-11 20:22:17.234 MutipleThreadPractice[27817:3509801] finish -[GCDDemoViewController asyncConcurrent] -------
{number = 1, name = main}2016-11-11 20:22:17.234 MutipleThreadPractice[27817:3516618] task A time 0 -----
{number = 3, name = (null)}2016-11-11 20:22:17.234 MutipleThreadPractice[27817:3516625] task B time 0 -----
{number = 4, name = (null)}2016-11-11 20:22:17.236 MutipleThreadPractice[27817:3516618] task A time 1 -----
{number = 3, name = (null)}2016-11-11 20:22:17.236 MutipleThreadPractice[27817:3516625] task B time 1 -----
{number = 4, name = (null)}2016-11-11 20:22:17.237 MutipleThreadPractice[27817:3516618] task A time 2 -----
{number = 3, name = (null)}2016-11-11 20:22:17.237 MutipleThreadPractice[27817:3516625] task B time 2 -----
{number = 4, name = (null)}2016-11-11 20:22:17.238 MutipleThreadPractice[27817:3516618] task A time 3 -----
{number = 3, name = (null)}2016-11-11 20:22:17.239 MutipleThreadPractice[27817:3516625] task B time 3 -----
{number = 4, name = (null)}2016-11-11 20:22:17.239 MutipleThreadPractice[27817:3516618] task A time 4 -----
{number = 3, name = (null)}2016-11-11 20:22:17.239 MutipleThreadPractice[27817:3516625] task B time 4 -----
{number = 4, name = (null)}

 

GCD group

dispatch_group_notify函数用来指定一个额外的block,该block将在group中所有任务完成后执行

-(void)gcdGroup{    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_group_t group = dispatch_group_create();    dispatch_group_async(group, queue, ^{                [NSThread sleepForTimeInterval:5];                NSLog(@"finish task 1");        /*加载图片1 */ });    dispatch_group_async(group, queue, ^{        [NSThread sleepForTimeInterval:1];                NSLog(@"finish task 2");        /*加载图片2 */ });        dispatch_group_async(group, queue, ^{        [NSThread sleepForTimeInterval:2];                NSLog(@"finish task 3");        /*加载图片3 */ });    dispatch_group_notify(group, dispatch_get_main_queue(), ^{        NSLog(@"do next step after all the tasks ");        // 合并图片    });}

打印内容

2016-11-11 20:24:04.883 MutipleThreadPractice[27817:3518196] finish task 22016-11-11 20:24:05.883 MutipleThreadPractice[27817:3518197] finish task 32016-11-11 20:24:08.887 MutipleThreadPractice[27817:3518158] finish task 12016-11-11 20:24:08.887 MutipleThreadPractice[27817:3509801] do next step after all the tasks

 

 

GCD Barrier

-(void)gcdBarrier{    dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-1");    });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-2");    });    dispatch_barrier_async(concurrentQueue, ^(){        NSLog(@"dispatch-barrier");    });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-3");    });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-4");    });}

打印

2016-11-11 20:25:31.036 MutipleThreadPractice[27817:3519239] dispatch-12016-11-11 20:25:31.036 MutipleThreadPractice[27817:3519324] dispatch-22016-11-11 20:25:31.037 MutipleThreadPractice[27817:3519324] dispatch-barrier2016-11-11 20:25:31.038 MutipleThreadPractice[27817:3519324] dispatch-32016-11-11 20:25:31.038 MutipleThreadPractice[27817:3519239] dispatch-4

 

 

子线程进行下载图片,完成后在主线程进行UI操作

-(void)backgroundDownloadImage{         NSLog(@"before download image");    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                NSURL * url = [NSURL                       URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];        NSData * data = [[NSData alloc]initWithContentsOfURL:url];        UIImage *image = [[UIImage alloc]initWithData:data];        if (data != nil) {            dispatch_async(dispatch_get_main_queue(), ^{                self.imageView.image = image;                NSLog(@"download the image data");            });        }    });        NSLog(@"end download image");}

 

打印内容

2016-11-11 20:27:00.944 MutipleThreadPractice[27817:3509801] before download image2016-11-11 20:27:00.945 MutipleThreadPractice[27817:3509801] end download image2016-11-11 20:27:01.359 MutipleThreadPractice[27817:3509801] download the image data

 

 

多窗口卖票模型

@interface GCDDemoViewController ()/*库存的火车票*/@property (nonatomic,assign) NSInteger numberOfTickets;/**账户余额*/@property (nonatomic,assign) float accountBalance;@property (nonatomic,strong) dispatch_queue_t sellTicketQueue;@implementation GCDDemoViewController-(dispatch_queue_t)sellTicketQueue{    if (!_sellTicketQueue) {        _sellTicketQueue=dispatch_queue_create("SellTicketQueue", DISPATCH_QUEUE_SERIAL);    }    return _sellTicketQueue;}- (void)sellTicket:(NSInteger)number {  self.numberOfTickets = self.numberOfTickets - 1;  self.accountBalance = self.accountBalance + 10;  NSLog(@"window == %ld ticket number==%ld balance=%.2f total value=%f", number,        (long)self.numberOfTickets, self.accountBalance,        self.numberOfTickets * 10 + self.accountBalance);}- (void)sellTicketsWithoutLock {  dispatch_queue_t queue1 =      dispatch_queue_create("com.sellTicket", DISPATCH_QUEUE_CONCURRENT);  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      [NSThread sleepForTimeInterval:0.001];      [self sellTicket:1];    }  });  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      [NSThread sleepForTimeInterval:0.002];      [self sellTicket:2];    }  });  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      [self sellTicket:3];      [NSThread sleepForTimeInterval:0.004];    }  });}

 

 

加锁对竞争性资源的读写进行限制

- (void)sellTicketsWithLock {  dispatch_queue_t queue1 =      dispatch_queue_create("com.sellTicket", DISPATCH_QUEUE_CONCURRENT);  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      @synchronized(self) {        [NSThread sleepForTimeInterval:0.001];        [self sellTicket:1];      }    }  });  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      @synchronized(self) {        [NSThread sleepForTimeInterval:0.002];        [self sellTicket:2];      }    }  });  dispatch_async(queue1, ^{    for (int i = 0; i < 1000; i++) {      @synchronized(self) {        [NSThread sleepForTimeInterval:0.004];        [self sellTicket:3];      }    }  });}

 

 

使用串行队列进行限制

- (void)sellTicketsWithSerialQueue {  dispatch_queue_t queue1 =      dispatch_queue_create("com.sellTicket", DISPATCH_QUEUE_CONCURRENT);  for (int i = 0; i < 1000; i++) {    dispatch_async(queue1, ^{      [NSThread sleepForTimeInterval:0.001];      [self sellTicketInSerialQueue];    });    dispatch_async(queue1, ^{      [NSThread sleepForTimeInterval:0.002];      [self sellTicketInSerialQueue];    });    dispatch_async(queue1, ^{      [NSThread sleepForTimeInterval:0.004];      [self sellTicketInSerialQueue];    });  }}- (void)sellTicketInSerialQueue {  dispatch_async(self.sellTicketQueue, ^{    self.numberOfTickets = self.numberOfTickets - 1;    self.accountBalance = self.accountBalance + 10;    NSLog(@"  ticket number==%ld balance=%.2f total value=%f",          (long)self.numberOfTickets, self.accountBalance,          self.numberOfTickets * 10 + self.accountBalance);  });}

 

 

信号量

 

常见业务场景,

1,多个网络请求返回以后同时做处理

 

在异步执行的代码中,只有当信号量>0时才能继续执行。这样可以控制最大并发的数量。也可以做异步任务的同步处理。

 

/创建信号量/            dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);            /创建全局并行/            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);            dispatch_group_t group = dispatch_group_create();            dispatch_group_async(group, queue, ^{                NSLog(@"处理事件A");                for (int i = 0; i<10000; i++) {                    NSLog(@"打印i %d",i);                }                dispatch_semaphore_signal(semaphore);            });            dispatch_group_async(group, queue, ^{                NSLog(@"处理事件B");                for (int i = 0; i<10000; i++) {                    NSLog(@"打印j %d",i);                }                dispatch_semaphore_signal(semaphore);            });            dispatch_group_async(group, queue, ^{                NSLog(@"处理事件C");                for (int i = 0; i<10000; i++) {                    NSLog(@"打印k %d",i);                }                dispatch_semaphore_signal(semaphore);            });            dispatch_group_async(group, queue, ^{                NSLog(@"处理事件D");                for (int i = 0; i<10000; i++) {                    NSLog(@"打印l %d",i);                }                dispatch_semaphore_signal(semaphore);            });            dispatch_group_notify(group, queue, ^{                     /四个请求对应四次信号等待/                    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);                    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);                    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);                    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);                    NSLog(@"处理事件E");            });

 

 

这个例子,控制了,最大的并发线程数是10.超过10个线程执行的话,就暂时停止加入新的任务。

// 创建队列组    dispatch_group_t group = dispatch_group_create();   // 创建信号量,并且设置值为10    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);       dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);       for (int i = 0; i < 100; i++)       {   // 由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);           dispatch_group_async(group, queue, ^{               NSLog(@"%i",i);               sleep(2);   // 每次发送信号则semaphore会+1,            dispatch_semaphore_signal(semaphore);           });       }

 

多次请求以后综合处理

 

- (dispatch_queue_t)uploadImageConcurrentQueue {  if (!_uploadImageConcurrentQueue) {    _uploadImageConcurrentQueue = dispatch_queue_create(        "com.hzt.uploadImageQueue", DISPATCH_QUEUE_CONCURRENT);  }  return _uploadImageConcurrentQueue;}- (void)multipleOperationDemo {  //并发下载多张图片,然后对所有的图片完成后。好处在于可以对更多的操作  NSArray *imageURLs = @[    @"http://zbimg.25pp.com/images/artwork/102/951610982_54x54.jpg",    @"http://zbimg.25pp.com/images/artwork/92/855031900_54x54.jpg",    @"http://zbimg.25pp.com/images/artwork/246/950137846_54x54.jpg"  ];  dispatch_async(self.uploadImageConcurrentQueue, ^{    // 创建信号量    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);    // 创建全局并行    for (NSString *url in imageURLs) {      NSMutableURLRequest *request =          [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionTask *task =          [session dataTaskWithRequest:request                     completionHandler:^(NSData *_Nullable data,                                         NSURLResponse *_Nullable response,                                         NSError *_Nullable error) {                       NSLog(@"deal with data here url == %@", url);                       dispatch_semaphore_signal(semaphore);                     }];      [task resume];    }    NSLog(@"image 2 %@", [NSThread currentThread]);    for (int i = 0; i < imageURLs.count; i++) {      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);    }    NSLog(@"image 3 %@", [NSThread currentThread]);  });}

 

2016-11-12 18:29:10.234 MutipleThreadPractice[4897:4101983] image 2 
{number = 2, name = (null)}2016-11-12 18:29:10.337 MutipleThreadPractice[4897:4101987] deal with data here url == http://zbimg.25pp.com/images/artwork/246/950137846_54x54.jpg2016-11-12 18:29:10.358 MutipleThreadPractice[4897:4101987] deal with data here url == http://zbimg.25pp.com/images/artwork/102/951610982_54x54.jpg2016-11-12 18:29:10.358 MutipleThreadPractice[4897:4101987] deal with data here url == http://zbimg.25pp.com/images/artwork/92/855031900_54x54.jpg2016-11-12 18:29:10.358 MutipleThreadPractice[4897:4101983] image 3
{number = 2, name = (null)}

 

 

参考资料

 

http://www.jianshu.com/p/943dcb9ad632

 

https://developer.apple.com/reference/dispatch?language=objc

 

iOS-图文表并茂,手把手教你GCD

 

浅谈GCD中的信号量

http://www.jianshu.com/p/04ca5470f212

 

 

转载于:https://my.oschina.net/u/2360054/blog/749328

你可能感兴趣的文章
C# 中的 App.config 文件配置
查看>>
LeetCode 队列与BFS--岛屿的数量
查看>>
jmeter-noguimodel
查看>>
Git使用++
查看>>
[C++]基本类型转换
查看>>
清除windows系统垃圾文件简易脚本(bat)
查看>>
Android WindowManager实现悬浮窗效果 (一)——与当前Activity绑定
查看>>
陶哲轩实分析 定理7.5.1 (方根判别法) 证明
查看>>
The direct sum of functions
查看>>
《Linux内核设计与实现》读书笔记(十五)- 进程地址空间(kernel 2.6.32.60)
查看>>
[C++] Swap Two Num
查看>>
详解ABBYY FineReader 12扫描亮度设置
查看>>
线程同步利与弊,线程同步的前提
查看>>
js的escape()、encodeURI()、encodeURIComponent()区别详解
查看>>
python2与python3的区别
查看>>
HDU2196-Computer
查看>>
cpp
查看>>
nginx 报错502Bad Gateway
查看>>
决定转移ubuntu
查看>>
Linux下查看文件内容时去掉空行和#开头的注释行
查看>>