iOS进阶ios开发面试题

iOS底层原理探索—多线程的经典面试题

2019-08-12  本文已影响14人  劳模007_Mars

探索底层原理,积累从点滴做起。大家好,我是Mars。

往期回顾

iOS底层原理探索—OC对象的本质
iOS底层原理探索—class的本质
iOS底层原理探索—KVO的本质
iOS底层原理探索— KVC的本质
iOS底层原理探索— Category的本质(一)
iOS底层原理探索— Category的本质(二)
iOS底层原理探索— 关联对象的本质
iOS底层原理探索— block的本质(一)
iOS底层原理探索— block的本质(二)
iOS底层原理探索— Runtime之isa的本质
iOS底层原理探索— Runtime之class的本质
iOS底层原理探索— Runtime之消息机制
iOS底层原理探索—RunLoop的本质
iOS底层原理探索—RunLoop的应用
iOS底层原理探索—多线程的本质

前言

多线程是iOS开发中很重要的一个环节,无论是开发过程还是在面试环节中,多线程出现的频率都非常高。我们会通过几篇文章的探索,深入浅出的分析多线程技术。
今天我们通过几道有关多线程的面试题,来帮助我们更加深入的了解多线程。

多线程的经典面试题

1、下面代码的执行结果是什么?

- (void)viewDidLoad {
    [super viewDidLoad];

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        NSLog(@"任务1");
        [self performSelector:@selector(test) withObject:nil afterDelay:1.0];
        NSLog(@"任务3");
    });
}
- (void)test {
    NSLog(@"任务2");
}

答案是任务1,任务3

我们先分析一下代码:我们在全局队列dispatch_get_global_queue(0, 0)中异步dispatch_async执行三个任务。我们在iOS底层原理探索—多线程的本质一文中讲到,串行队列异步执行会开启子线程,说明三个任务都在子线程中执行,其中任务2是通过performSelector:withObject:afterDelay:方法延迟1秒执行。那么为什么任务2没有打印呢?

原因就在于performSelector:withObject:afterDelay:方法的本质是往RunLoop中添加定时器,但是子线程默认情况下没有RunLoop,需要手动创建,所以test方法无法执行,任务2自然也不会打印

下面我们手动为子线程开启RunLoop测试一下:

手动启动RunLoop后.png
可以看到,在启动RunLoop之后,任务2被执行,而且通过打印时间可以看出,任务2确实是在1秒后执行。

如果我们把performSelector:withObject:afterDelay:方法替换成performSelector:withObject:方法结果还会一样吗?

performSelector-withObject-方法执行结果.png
任务1,任务2,任务3直接打印了。
这是由于performSelector:withObject:方法的本质是通过消息机制来调用的,所以能够执行任务2。我们可以通过performSelector:withObject:afterDelay:方法的源码得到证明:
源码.png

2、下面代码的执行结果是什么?

- (void)viewDidLoad {
    [super viewDidLoad];
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"任务1");
    }];
    [thread start];

    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}
- (void)test {
    NSLog(@"任务2");
}

答案是打印完任务1,程序崩溃

我们在子线程thread中执行任务1,等任务1执行完后再在子线程中执行test方法。但是执行完任务1后,子线程thread就被销毁了,所以接着要在子线程中执行test方法时会崩溃。

当然,为子线程启动RunLoop同样也可以解决程序崩溃的问题。大家可以测试一下。

队列组

队列组是用来管理队列中任务的执行,使用队列组异步函数来封装任务, 然后提交到队列中。队列组通过dispatch_group_notify函数来监听任务执行。

我们通过下面一道题目来帮助理解队列组:

异步并发执行任务1、任务2,等任务1、任务2都执行完后回到主线程执行任务3

我们可以通过GCD的队列组来实现上面题目的要求:


队列组的应用.png

通过打印我们看到,任务1和任务2在子线程中并发执行完后,回到主线程中执行任务3。

其中dispatch_group_notify函数会在队列组dispatch_group_t执行完队列组中的任务后接收到通知,来执行其他任务。

更多技术知识请关注公众号
iOS进阶


iOS进阶.jpg
上一篇下一篇

猜你喜欢

热点阅读