1.简述GCD,NSThread,NSOperation使用,各自优缺点
NSThread:
–优点:NSThread 比其他两个轻量级,使用简单
–缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销
NSOperation、GCD:
优点:不需要关心线程管理,数据同步的事情。
两者区别:
NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
GCD主要与block结合使用。代码简洁高效
1. 性能:GCD更接近底层,而NSOperationQueue则更高级抽象,所以GCD在追求性能的底层操作来说,是速度最快的。这取决于使用Instruments进行代码性能分析,如有必要的话
2. 从异步操作之间的事务性,顺序行,依赖关系。GCD需要自己写更多的代码来实现,而NSOperationQueue已经内建了这些支持
3. 如果异步操作的过程需要更多的被交互和UI呈现出来,NSOperationQueue会是一个更好的选择。底层代码中,任务之间不太互相依赖,而需要更高的并发能力,GCD则更有优势
2.GCD底层原理是什么?
GCD实现原理: GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“池”中的线程是可以重用的,当一段时间后这个线程没有被调用胡话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统自动来维护,不需要我们程序员来维护(看到这句话是不是很开心?)
而我们程序员需要关心的是什么呢?我们只关心的是向队列中添加任务,队列调度即可。
如果队列中存放的是同步任务,则任务出队后,底层线程池中会提供一条线程供这个任务执行,任务执行完毕后这条线程再回到线程池。这样队列中的任务反复调度,因为是同步的,所以当我们用currentThread打印的时候,就是同一条线程。
如果队列中存放的是异步的任务,(注意异步可以开线程),当任务出队后,底层线程池会提供一个线程供任务执行,因为是异步执行,队列中的任务不需等待当前任务执行完毕就可以调度下一个任务,这时底层线程池中会再次提供一个线程供第二个任务执行,执行完毕后再回到底层线程池中。
这样就对线程完成一个复用,而不需要每一个任务执行都开启新的线程,也就从而节约的系统的开销,提高了效率。在iOS7.0的时候,使用GCD系统通常只能开5~8条线程,iOS8.0以后,系统可以开启很多条线程,但是实在开发应用中,建议开启线程条数:3~5条最为合理。
3.给定一个网络请求依赖场景,用自己熟悉的方式解决
4.常用哪种锁?原理是什么
https://juejin.im/post/5d554410f265da03b21532cd#heading-53
gcd栅栏 nslock @synchronized
5.atomic一定是线程安全的吗?
用atomic修饰成员变量,会给成员变量的getter 和 setter方法加锁,使访问每次只能进行一个,避免多个线程同时操作成员变量.
atomic 只负责直接赋值和读取的线程安全,比如数组,直接赋值和读取是安全的,但是添加和移除不在负责权限内,不安全
6.NSArray如何保证线程安全?
将数组的写(插入、修改、删除)操作放进队列中dispatch_barrier函数中,这样当进行写的操作时,会先等待前面的读的任务完成后再执行写操作;而且后面的读任务也要等待dispatch_barrier中的写操作执行完成后才会被执行。
7.开启一条线程的方法?线程可以取消吗?
NSOperation - (void)cancel; 可取消操作,实质是标记 isCancelled 状态。
GCDiOS8之后可以调用dispatch_block_cancel来取消(需要注意必须用dispatch_block_create创建dispatch_block_t)定义外部变量,用于标记block是否需要取消
8.子线程中调用connection方法,为什么不回调?因为没有加入runloop,执行完任务就销毁了,所以没有回调。
9.那子线程中的autorelease变量什么时候释放?
10.子线程里面,需要加autoreleasepool吗
每一个线程创建的时候就会有一个autorelease pool的创建,并且在线程退出的时候,清空整个autorelease pool。(ps:如果在子线程中设置一个循环,autorelease对象确实无法释放)
https://zhuanlan.zhihu.com/p/26796146
在子线程你创建了 Pool 的话,产生的 Autorelease 对象就会交给 pool 去管理。如果你没有创建 Pool ,但是产生了 Autorelease 对象,就会调用 autoreleaseNoPage 方法。在这个方法中,会自动帮你创建一个 hotpage(hotPage 可以理解为当前正在使用的 AutoreleasePoolPage,如果你还是不理解,可以先看看 Autoreleasepool 的源代码,再来看这个问题 ),并调用page->add(obj)将对象添加到 AutoreleasePoolPage 的栈中,也就是说你不进行手动的内存管理,也不会内存泄漏啦!StackOverFlow 的作者也说道,这个是 OS X 10.9+和 iOS 7+ 才加入的特性。并且苹果没有对应的官方文档阐述此事,但是你可以通过源码了解。
11.项目里面遇到过死锁吗?怎么解决?数据库访问本来就是线程安全的,不会造成死锁啊。什么是死锁?
所谓死锁,通常指有两个线程T1和T2都卡住了,并等待对方完成某些操作。T1不能完成是因为它在等待T2完成。但T2也不能完成,因为它在等待T1完成。于是大家都完不成,就导致了死锁(DeadLock)。
12.进程和线程的区别?同步异步的区别?串行和并发的区别?
1、首先是定义
进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。
线程:单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。
2、一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。
13.线程间通信?
https://www.jianshu.com/p/aacd3409f14b
14.GCD的一些常用的函数?(group,barrier,信号量,线程同步)
15、OC你了解的锁有哪些?在你回答基础上进行二次提问;
追问一:自旋和互斥对比?
追问二:用C/OC/C++,任选其一,实现自旋或互斥?口述即可!
https://www.jianshu.com/p/3a50d1805655
网友评论