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 : NSObject
MKJSingletonH
@end
@implementation ManagerHelper
MKJSinletonM
@end
注:这里为什么需要用Static进行修饰,static保证只有本文件才能访问,这样就能形成单例,但是如果不用static修饰,外部也一样能访问,这个时候外部如果置为nil之后,这个对象就不存在了,再也不会创建了,dispatch_once只会执行一次,这样肯定不对的
非常简单的介绍,这里有个Demo,需要的朋友可以下载看看基础用法先,文章头部有介绍GCD死锁解锁的案例文章,需要的也可以看看
本文Demo传送门