当前位置: 首页 > news >正文

iOS的一些面试题分析总结(1)


本篇主要说一下多线程的东西,因为东西比较多,所以直接拿出一整个篇幅来说它了。

3、 多线程的底层实现? 

1、先说一下什么是进程,什么是线程、什么是多线程。

进程是资源分配的单位,线程是调度运行的基本单位。多线程简而言之就是一个应用程序中,多个线程同步执行;多用于处理用户界面响应和网络访问的处理的同事进行,通常用子线程处理如网络访问等一些比较耗时的操作,同时不影响主线程在用户界面对用户操作的响应。

2、 Mach

Mach是第一个以多线程方式处理任务的系统,因此多线程的底层实现机制是基于Mach的线程,开发中很少用Mach级的线程,因为Mach级的线程没有提供多线程的基本特征,线程之间是独立的。

3、 开发中实现多线程的方案

1、C语言的pthread

2、OC的NSThread

3、 GCD

4、NSOperation和NSOperationQueue

 

4、线程间怎么通信?

这里借用这个问题,比较详细的回顾一下比较常用的三种多线程方案: NSThread、GCD、NSOperation和NSOperationQueue。

1、NSThread

先看它的线程间通讯:

1 //去子线程执行耗时任务
2 //    [self performSelectorInBackground:@selector(downloadSomething:) withObject:url];
3     
4 //    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadSomething:) object:url];
5 //    // 设置线程的优先级(0.0 - 1.0,1.0最高级)
6 //    //thread.threadPriority = 1.0;
7 //    [thread start];
8     
9     [NSThread detachNewThreadSelector:@selector(downloadSomething:) toTarget:self withObject:url];

去子线程执行任务的三种方式。

1 //回到主线程刷新界面
2     //    [self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
3     
4     //    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
5     
6     [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];

耗时任务执行完毕之后回主线程刷新界面的三种方式。

还有一些其他的简单操作可以去demo看一下,这里就不多赘述了。

NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象。但是需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销。

2、GCD

GCD的线程间通讯:

 1     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 2         
 3         NSData *data = [NSData dataWithContentsOfURL:url];
 4         NSData *data1 = [NSData dataWithContentsOfURL:url1];
 5         UIImage *image = [UIImage imageWithData:data];
 6         UIImage *image1 = [UIImage imageWithData:data1];
 7         dispatch_async(dispatch_get_main_queue(), ^{
 8             self.imageView.image = image;
 9             self.imageView1.image = image1;
10         });
11         
12     });

在子线程下载两张图片,回到主线程更新界面。

下面再看一下Dispatch Group:

Dispatch Group可以用来阻塞一个线程, 直到group关联的所有的任务完成执行。适用于有时候你必须等待任务完成的结果,然后才能继续后面的处理的情况。但是下面的这种场景其实个人认为是不需要这么做的,用上面的方式就好了。这里只为演示代码。

 1 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 2     
 3     dispatch_async(queue, ^{
 4         dispatch_group_t group = dispatch_group_create();
 5         dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 6         __block UIImage *image = nil; //注意block给image赋值,必须加__block前缀
 7         __block UIImage *image1 = nil;
 8         //往组中添加任务
 9         dispatch_group_async(group, queue, ^{
10             NSData *data = [NSData dataWithContentsOfURL:url];
11             image = [UIImage imageWithData:data];
12         });
13         //往组中添加任务
14         dispatch_group_async(group, queue, ^{
15             NSData *data1 = [NSData dataWithContentsOfURL:url1];
16             image1 = [UIImage imageWithData:data1];
17         });
18         // 等待组中的任务执行完毕,回到主线程执行block回调
19         dispatch_group_notify(group, dispatch_get_main_queue(), ^{
20             self.imageView.image = image;
21             self.imageView1.image = image1;
22         });
23     });

还有以下GCD的其他用法,写在demo里了,这里就不再赘述。下面看NSOperation和NSOperationQueue。

3、NSOperation和NSOperationQueue

 1     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
 2     
 3     __block UIImage *image0 = nil;
 4     __block UIImage *image1 = nil;
 5     
 6     // 创建3个操作
 7     NSOperation *a = [NSBlockOperation blockOperationWithBlock:^{
 8         NSData *data = [NSData dataWithContentsOfURL:url0];
 9         image0 = [UIImage imageWithData:data];
10         NSLog(@"当前调用线程:%@", [NSThread currentThread]);
11     }];
12     NSOperation *b = [NSBlockOperation blockOperationWithBlock:^{
13         NSData *data = [NSData dataWithContentsOfURL:url1];
14         image1 = [UIImage imageWithData:data];
15         NSLog(@"当前调用线程:%@", [NSThread currentThread]);
16     }];
17     NSOperation *c = [NSBlockOperation blockOperationWithBlock:^{
18         [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image0 waitUntilDone:NO];
19         [self.imageView1 performSelectorOnMainThread:@selector(setImage:) withObject:image1 waitUntilDone:NO];
20     }];
21     
22     // 添加依赖
23     [b addDependency:a];
24 //    [c addDependency:a];
25     [c addDependency:b];
26     
27     // 执行操作
28     [queue addOperation:a];
29     [queue addOperation:b];
30     [queue addOperation:c];

GCD和NSOperationQueue都属于不需要自己直接操作线程的,本人一般情况下都直接用GCD比较多,一来因为它高效,二来简洁方便。但是在像上面需要顺序执行,也就是需要用到依赖的时候,用NSOperationQueue比较方便。

同样的,其他关于NSOperation和NSOperationQueue的使用在这里不多赘述,希望再多了解一些的可以自行去demo看一下代码。

demo:https://github.com/alan12138/Interview-question/tree/master/4

 

5、GCD内部怎么实现的?

1、 iOSOS X的核心是XNU内核,GCD是基于XNU内核实现的

2、 GCDAPI全部在libdispatch库中

3、 GCD的底层实现主要有Dispatch QueueDispatch Source

Dispatch Queue :管理block(操作)

Dispatch Source :处理事件

 

6、 你用过NSOperationQueue么?如果用过或者了解的话,你为什么要使用NSOperationQueue,实现了什么?请描述它和GCD的区别和类似的地方(提示:可以从两者的实现机制和适用范围来描述)。

1、GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装

2、 GCD的执行速度比NSOperationQueue

3、GCD只支持FIFO的队列,NSOperationQueue可以很方便地调整执行顺序、设置最大并发数量

4、 NSOperationQueue可以在轻松在Operation间设置依赖关系,而GCD需要写很多的代码才能实现

5、 NSOperationQueue支持KVO,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld

6、如何选择:任务之间不太互相依赖:GCD;任务之间有依赖\或者要监听任务的执行情况:NSOperationQueue

 

7.、既然提到GCD,那么问一下在使用GCD以及block时要注意些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么区别,需要注意些什么?

Block的使用注意:

1、 block的内存管理(前面的题有讲到block)

2、防止强引用循环

避免强引用循环:

* 非ARC(MRC):__block(还有修改外部临时变量)

 ARC:__weak\__unsafe_unretained

转载于:https://www.cnblogs.com/alan12138/p/5810432.html

相关文章:

  • sql中的group by
  • java的finally语句
  • 各种编程语言变量的数据类型
  • java解惑你知多少(一)
  • 《Entity Framework 6 Recipes》中文翻译系列 (7) -----第二章 实体数据建模基础之拆分实体到多表以及拆分表到多实体...
  • java解惑你知多少(二)
  • lnmp的使用
  • java解惑你知多少(三)
  • linux挂载windows共享文件夹
  • java解惑你知多少(四)
  • Android selector的使用
  • java解惑你知多少(五)
  • 快速傅里叶变换FFT学习小记
  • java解惑你知多少(六)
  • ThinkPHP3.2.3扩展之生成PDF文件(MPDF)
  • Apache的80端口被占用以及访问时报错403
  • Babel配置的不完全指南
  • Fastjson的基本使用方法大全
  • Java新版本的开发已正式进入轨道,版本号18.3
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • oldjun 检测网站的经验
  • Python打包系统简单入门
  • python学习笔记-类对象的信息
  • Vue学习第二天
  • Vultr 教程目录
  • webpack入门学习手记(二)
  • 编写符合Python风格的对象
  • 编写高质量JavaScript代码之并发
  • 服务器从安装到部署全过程(二)
  • 基于 Babel 的 npm 包最小化设置
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 想写好前端,先练好内功
  • 运行时添加log4j2的appender
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • 积累各种好的链接
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • # 安徽锐锋科技IDMS系统简介
  • (1) caustics\
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (C++17) optional的使用
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (十二)springboot实战——SSE服务推送事件案例实现
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET性能优化(文摘)
  • /etc/shadow字段详解
  • @Autowired自动装配
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用