多线程 & 网络

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中有两个任务:block1block2

2>block2排在block1后面,所以需要等待block1执行完,block2才能执行

3>block1需要等待dispatch_sync函数返回才能执行完,而dispatch_sync函数需要等待block2执行完才会返回

4>block1block2互相等待,导致死锁

3,总结

使用dispatch_sync函数往当前并且是串行的队列中添加任务,就会产生死锁

- (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
上一篇下一篇

猜你喜欢

热点阅读