iOS中的多线程(关于GCD的队列和任务)

608 阅读1分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

队列的创建

创建自定义并发队列和串行队列

//并行队列
dispatch_queue_t queue = dispatch_queue_create("com.gcd.queue", DISPATCH_QUEUE_CONCURRENT);

//串行队列
dispatch_queue_t queue = dispatch_queue_create("com.gcd.queue", NULL);

参数1:队列名称,命名规则为FQDN,应用名称ID的倒序 + queue名字
参数2:队列类型,设置为 NULL,默认创建串行队列(DISPATCH_QUEUE_SERIAL)。创建并行队列将参数设置为 DISPATCH_QUEUE_CONCURRENT

获得全局并发队列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

参数1:优先级
DISPATCH_QUEUE_PRIORITY_HIGH//高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT//默认优先级
DISPATCH_QUEUE_PRIORITY_LOW//低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND//后台优先级
参数2:目前没有意义,官方文档提示传0)

获得全局主队列(特殊的串行队列)

  • 放在主队列中的任务,都会放在主线程中执行
  • 主队列的实质上就是一个普通的串行队列,只是因为默认情况下,当前代码是放在主队列中的,然后主队列中的代码,有都会放到主线程中去执行
dispatch_queue_t queue = dispatch_get_main_queue();

任务和队列不同组合方式的区别

并发队列 + 异步函数

  • 可以开启多个线程,任务同时执行(异步函数具备开启新线程)

示例:

dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//异步函数
dispatch_async(concurrentQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--1--%@",[NSThread currentThread]);
    }
});

//异步函数
dispatch_async(concurrentQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_50.png

并发队列 + 同步函数

  • 在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务
  • 按顺序执行的原因:虽然并发队列可以开启多个线程,并且同时执行多个任务,但是同步函数不具备开启新线程的能力,所以也就不存在并发。因此任务只能一个接一个按顺序执行,不能同时被执行。

示例:

dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//同步函数
dispatch_sync(concurrentQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--1--%@",[NSThread currentThread]);
    }
});

//同步函数
dispatch_sync(concurrentQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_54.png

串行队列 + 异步函数

  • 会开新线程,任务是串行的,执行完一个再执行下一个(异步函数具备开启新线程)

示例:

dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.serialQueue", DISPATCH_QUEUE_SERIAL);

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//异步函数
dispatch_async(serialQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--1--%@",[NSThread currentThread]);
    }
});

//异步函数
dispatch_async(serialQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_53.png

串行队列 + 同步函数

  • 所有任务都是在当前线程(主线程)中执行的,并没有开启新的线程(同步函数不具备开启新线程)

示例:

dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.serialQueue", DISPATCH_QUEUE_SERIAL);

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//同步函数
dispatch_sync(serialQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--1--%@",[NSThread currentThread]);
    }
});

//同步函数
dispatch_sync(serialQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_52.png

主队列 + 异步函数

  • 所有任务都是在当前线程(主线程)中执行的,并没有开启新的线程(虽然异步执行具备开启线程的能力,但因为是主队列,所以所有任务都在主线程中)

示例:

dispatch_queue_t mainQueue = dispatch_get_main_queue();

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//异步函数
dispatch_async(mainQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--1--%@",[NSThread currentThread]);
    }
});

//异步函数
dispatch_async(mainQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"异步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_55.png

主队列 + 同步函数

主队列中加同步任务和主线程本身的任务两者之间相互等待,阻塞了主队列,最终造成了主队列所在的线程(主线程)死锁问题

示例:

dispatch_queue_t mainQueue = dispatch_get_main_queue();

NSLog(@"当前线程--0--%@",[NSThread currentThread]);

//同步函数
dispatch_sync(mainQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--1--%@",[NSThread currentThread]);
    }
});

//同步函数
dispatch_sync(mainQueue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"同步函数--2--%@",[NSThread currentThread]);
    }
});

log: Snip20211106_56.png

各种队列的执行效果

类型并发队列串行队列主队列
同步(sync)不会开新线程
串行执行任务
不会开新线程
串行执行任务
死锁卡住不执行
异步(async)会开新线程
并行执行任务
会开新线程
串行执行任务
不会开新线程
串行执行任务