GCD的介绍有另外一篇博客专门写了下,需要看的可以点击以下传送门GCD线程死锁解锁案例分析,这里主要记录下基本的API使用以及两种单例的创建方式
1.GCD同步异步并发串行排列组合的集中基本形式
- (void)asynchSerial{ dispatch_queue_t queue1 = dispatch_queue_create("COM.MKJ.COM", DISPATCH_QUEUE_SERIAL); dispatch_async(queue1, ^{ NSLog(@"------1,%@",[NSThread currentThread]); }); dispatch_async(queue1, ^{ NSLog(@"------2,%@",[NSThread currentThread]); }); dispatch_async(queue1, ^{ NSLog(@"------3,%@",[NSThread currentThread]); }); NSLog(@"asynchSerial------end");}- (void)synchSerial{ dispatch_queue_t queue1 = dispatch_queue_create("COM.MKJ.COM", DISPATCH_QUEUE_SERIAL); dispatch_sync(queue1, ^{ NSLog(@"------1,%@",[NSThread currentThread]); }); dispatch_sync(queue1, ^{ NSLog(@"------2,%@",[NSThread currentThread]); }); dispatch_sync(queue1, ^{ NSLog(@"------3,%@",[NSThread currentThread]); }); NSLog(@"synchSerial------end");}- (void)synchConcurrent{ dispatch_queue_t queue1 = dispatch_queue_create("COM.MKJ.COM", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(queue1, ^{ NSLog(@"------1,%@",[NSThread currentThread]); }); dispatch_sync(queue1, ^{ NSLog(@"------2,%@",[NSThread currentThread]); }); dispatch_sync(queue1, ^{ NSLog(@"------3,%@",[NSThread currentThread]); }); NSLog(@"synchConcurrent------end");}- (void)asynchConcurrent{ dispatch_queue_t queue1 = dispatch_queue_create("COM.MKJ.COM", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue1, ^{ NSLog(@"------1,%@",[NSThread currentThread]); }); dispatch_async(queue1, ^{ NSLog(@"------2,%@",[NSThread currentThread]); }); dispatch_async(queue1, ^{ NSLog(@"------3,%@",[NSThread currentThread]); }); NSLog(@"asynchConcurrent------end");}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
简单概括如下:
项目 | 同步(sync) | 异步(async) | 串行当前线程,顺序执行另一个线程,顺序执行并发当前线程,顺序执行另一个线程,同时执行可以看出同步和异步就是开线程的能力,同步执行必然一个个顺序执行在当前线程,而异步执行可以根据队列不同来确定顺序还是同步并发执行
2.最基本的线程间通讯方式
dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURL *url = [NSURL URLWithString:@"https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRCfHVwGXGvrpCBplQieSKsLgfBULL8ZZXSzosPFdoZsvjDlqnOrKK_w58"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; NSLog(@"获取资源%@",[NSThread currentThread]); dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; NSLog(@"加载资源%@",[NSThread currentThread]); }); });
3.其他Barrier,apply,after,Group等常用API
- (void)barrier{ dispatch_queue_t queue = dispatch_queue_create("com.mkj.hehe", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"--------1,%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ for (NSInteger i = 0; i < 10; i ++) { NSLog(@"--------2%ld,%@",i,[NSThread currentThread]); } }); dispatch_barrier_async(queue, ^{ NSLog(@"--------3,%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------4,%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------5,%@",[NSThread currentThread]); });}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- (void)apply{ dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) { NSLog(@"%ld,%@",index,[NSThread currentThread]); });}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- (void)delay{ NSLog(@"开始了"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"我才开始"); }); [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];}- (void)run{ NSLog(@"run");}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- (void)group{ // 并发队列 dispatch_queue_t queue = dispatch_queue_create("com.mkj.hh", DISPATCH_QUEUE_CONCURRENT) // 线程组 dispatch_group_t group = dispatch_group_create() // 任务1加入组 dispatch_group_async(group, queue, ^{ NSURL *url = [NSURL URLWithString:@"https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQxex7CvJ0pArQ8NHwXMaZ8fSt3ALAZBlljTQVlDsh6AIegeMjWWMoSVtej"] NSData *data = [NSData dataWithContentsOfURL:url] self.image1 = [UIImage imageWithData:data] }) // 任务2加入组 dispatch_group_async(group, queue, ^{ // 这里可以一样是耗时的网络请求,暂时处理成本地的 self.image2 = [UIImage imageNamed:@"Play"] }) // 任务完成之后统一通知 dispatch_group_notify(group, queue, ^{ // 这里的queue如果是mainQueue的话就可以直接回到主线程操作需要的UI // 现在还是在并发队列里面 进行图片合成 还是放在子线程 UIGraphicsBeginImageContext(CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width)) [self.image1 drawInRect:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width)] [self.image2 drawInRect:CGRectMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.width/2, 30, 40)] UIImage *image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() // 回到主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image }) })}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
4.两种方式实现单例
static id obj;+ (instancetype)shareInstance{ @synchronized (self) { if (!obj) { obj = [[self alloc] init]; } } return obj;}+ (instancetype)allocWithZone:(struct _NSZone *)zone{ @synchronized (self) { if (!obj) { obj = [super allocWithZone:zone]; } } return obj;}- (id)copyWithZone:(NSZone *)zone{ return obj;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
#define MKJSingletonH + (instancetype)shareManager;#define MKJSinletonM \static id obj; \ \+ (instancetype)shareManager \{ \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ obj = [[self alloc] init]; \ }); \ return obj; \} \ \+ (instancetype)allocWithZone:(struct _NSZone *)zone \{ \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ obj = [super allocWithZone:zone]; \ }); \ return obj; \} \ \- (id)copyWithZone:(NSZone *)zone \{ \ return obj; \}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
抽成宏之后可以直接进行调用就OK
@interface ManagerHelper : NSObjectMKJSingletonH@end@implementation ManagerHelperMKJSinletonM@end
注:这里为什么需要用Static进行修饰,static保证只有本文件才能访问,这样就能形成单例,但是如果不用static修饰,外部也一样能访问,这个时候外部如果置为nil之后,这个对象就不存在了,再也不会创建了,dispatch_once只会执行一次,这样肯定不对的
非常简单的介绍,这里有个Demo,需要的朋友可以下载看看基础用法先,文章头部有介绍GCD死锁解锁的案例文章,需要的也可以看看
本文Demo传送门