iOS多线程:GCD基础篇
2020-03-23 本文已影响0人
码小菜
别墅
目录
一,函数
二,队列
三,组合
四,通信
五,死锁
一,函数
1,同步:在当前线程中执行任务,不具备开启新线程的能力
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
2,异步:在新线程中执行任务,具备开启新线程的能力
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
二,队列
1,串行队列:多个任务按顺序执行
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
2,并发队列:多个任务同时执行
dispatch_queue_t concurrentQueue = dispatch_queue_create("MyConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
// 每个优先级全局只有一个
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3,主队列(属于串行队列):多个任务在主线程中按顺序执行
// 全局只有一个
dispatch_queue_t mainQueue = dispatch_get_main_queue();
三,组合
1,同步+串行队列:多个任务在当前线程中按顺序执行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
// 打印
任务1---1---<NSThread: 0x60000139d040>{number = 1, name = main}
任务1---2---<NSThread: 0x60000139d040>{number = 1, name = main}
任务1---3---<NSThread: 0x60000139d040>{number = 1, name = main}
任务2---1---<NSThread: 0x60000139d040>{number = 1, name = main}
任务2---2---<NSThread: 0x60000139d040>{number = 1, name = main}
任务2---3---<NSThread: 0x60000139d040>{number = 1, name = main}
任务3---1---<NSThread: 0x60000139d040>{number = 1, name = main}
任务3---2---<NSThread: 0x60000139d040>{number = 1, name = main}
任务3---3---<NSThread: 0x60000139d040>{number = 1, name = main}
2,同步+并发队列:多个任务在当前线程中按顺序执行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t concurrentQueue = dispatch_queue_create("MyConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
// 打印
任务1---1---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务1---2---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务1---3---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务2---1---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务2---2---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务2---3---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务3---1---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务3---2---<NSThread: 0x600001eae0c0>{number = 1, name = main}
任务3---3---<NSThread: 0x600001eae0c0>{number = 1, name = main}
3,同步+主队列:死锁
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
4,异步+串行队列:多个任务在一个新线程中按顺序执行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
// 打印
任务1---1---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务1---2---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务1---3---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务2---1---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务2---2---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务2---3---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务3---1---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务3---2---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
任务3---3---<NSThread: 0x600003a40b80>{number = 6, name = (null)}
5,异步+并发队列:多个任务在多个新线程中同时执行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(globalQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(globalQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
// 打印
任务1---1---<NSThread: 0x6000024eff40>{number = 4, name = (null)}
任务2---1---<NSThread: 0x600002465380>{number = 8, name = (null)}
任务3---1---<NSThread: 0x60000249c8c0>{number = 9, name = (null)}
任务1---2---<NSThread: 0x6000024eff40>{number = 4, name = (null)}
任务3---2---<NSThread: 0x60000249c8c0>{number = 9, name = (null)}
任务2---2---<NSThread: 0x600002465380>{number = 8, name = (null)}
任务1---3---<NSThread: 0x6000024eff40>{number = 4, name = (null)}
任务3---3---<NSThread: 0x60000249c8c0>{number = 9, name = (null)}
任务2---3---<NSThread: 0x600002465380>{number = 8, name = (null)}
6,异步+主队列:多个任务在主线程中按顺序执行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务1---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务2---%d---%@", i + 1, [NSThread currentThread]);
}
});
dispatch_async(mainQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"任务3---%d---%@", i + 1, [NSThread currentThread]);
}
});
}
// 打印
任务1---1---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务1---2---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务1---3---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务2---1---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务2---2---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务2---3---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务3---1---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务3---2---<NSThread: 0x600000b57f00>{number = 1, name = main}
任务3---3---<NSThread: 0x600000b57f00>{number = 1, name = main}
7,总结
串行队列 | 并发队列 | 主队列 | |
---|---|---|---|
同步 | 当前线程/按顺序执行 | 当前线程/按顺序执行 | 死锁 |
异步 | 一个新线程/按顺序执行 | 多个新线程/同时执行 | 主线程/按顺序执行 |
四,通信
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"在子线程请求数据---%@", [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"回主线程刷新UI---%@", [NSThread currentThread]);
});
});
}
// 打印
在子线程中请求数据---<NSThread: 0x600002714200>{number = 4, name = (null)}
回主线程中刷新UI---<NSThread: 0x600002744240>{number = 1, name = main}
五,死锁
1,场景一
- 代码
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// 将block同步添加到mainQueue中
dispatch_sync(mainQueue, ^{
NSLog(@"2");
});
NSLog(@"3");
}
// 打印
1
- 分析
1>当执行到
dispatch_sync
函数时,mainQueue
中有两个任务:dispatch_sync
函数和block
2>
block
排在dispatch_sync
函数后面,所以需要等待dispatch_sync
函数执行完,block
才能执行3>
dispatch_sync
函数的特点是需要等待block
执行完,它才会返回4>
dispatch_sync
函数和block
互相等待,导致死锁
2,场景二
- 代码
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
// 将block1异步添加到serialQueue中
dispatch_async(serialQueue, ^{ // block1
NSLog(@"2");
// 将block2同步添加到serialQueue中
dispatch_sync(serialQueue, ^{ // block2
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
// 打印
1
5
2
- 分析
1>当执行到
dispatch_sync
函数时,serialQueue
中有两个任务:block1
和block2
2>
block2
排在block1
后面,所以需要等待block1
执行完,block2
才能执行3>
block1
需要等待dispatch_sync
函数返回才能执行完,而dispatch_sync
函数需要等待block2
执行完才会返回4>
block1
和block2
互相等待,导致死锁
3,总结
使用
dispatch_sync
函数往当前
并且是串行
的队列中添加任务,就会产生死锁
- 非
dispatch_sync
函数:dispatch_async
函数的特点是立即返回,无需等待任务执行完
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"2");
dispatch_async(serialQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
// 打印
1
5
2
4
3
- 非当前:任务不在同一个队列中,无需互相等待
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t serialQueue = dispatch_queue_create("MySerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("MySerialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"2");
dispatch_sync(serialQueue2, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
// 打印
1
5
2
3
4
- 非串行:并发队列中的任务可以同时执行,无需互相等待
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t concurrentQueue = dispatch_queue_create("MyConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"2");
dispatch_sync(concurrentQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
@end
// 打印
1
5
2
3
4