1.多线程的优点和缺点分别是什么?
答:优点:
1
、将耗时较长的操作(网络请求、图片下载、音频下载、数据库访问等)放在子线程中执行,可以防止主线程的卡死;
2
、可以发挥多核处理的优势,提升
cpu
的使用率。
缺点:
1
、每开辟一个子线程就消耗一定的资源;
2
、会造成代码的可读性变差;
3
、如果出现多个线程同时访问一个资源,会出现资源争夺的情况
3. 2.NSOperationQueue
中有一个属性叫
maxConcurrentCount
即最大并发数。这里所谓的最大并发数指的是什么含义?
答:这里的最大并发数指得是在队列中同时执行的任务的个数。有很多人会认为是所分配的线程的个数。其实不是的。因为线程的个数的多少取决于系统,系统会分配合适的线程数量来保证这些任务并发执行的,作为程序员我们是没办法控制的
4
、
NSThread
中的
Runloop
的作用,如何使用?
每个线程
(NSThread)
对象中内部都有一个
run loop
(
NSRunLoop
)对象用来循环处理输入事件,处理的事件包括两类,一是来自
Input sources
的异步事件,一是来自
Timer sources
的同步事件
;
run Loop
在处理输入事件时会产生通知,可以通过
Core Foundation
向线程中添加
run-loop observers
来监听特定事件
,
以在监听的事件发生时做附加的处理工作。
主线程的
Run Loop
会在
App
运行时自动运行,子线程中需要手动运行。
Run Loop
就是一个处理事件源的循环,你可以控制这个
Run Loop
运行多久,如果当前没有事件发生,
Run Loop
会让这个线程进入睡眠状态
(
避免再浪费
CPU
时间
)
,如果有事件发生,
Run Loop
就处理这个事件。
如果子线程进入一个循环需要不断处理一些事件,那么设置一个
Run Loop
是最好的处理方式,如果需要
Timer
,那么
Run Loop
就是必须的。
开发中遇到的需要使用
Run Loop
的情况有:
需要使用
Port
或者自定义
Input Source
与其他线程进行通讯。
子线程中使用了定时器
使用任何
perform mSelector*****
到子线程中运行方法
使用子线程去执行周期性任务
NSURLConnection
在子线程中发起异步请求
10
)
OC
中创建线程的方法是什么?如果在主线程中执行代码,方法是什么
线程创建有三种方法
:
使用
NSThread
创建、使用
GCD
的
dispatch
、使用子类化的
NSOperation,
然后将其加入
NSOperationQueue;
在主线程执行代码
,
方法是
performSelectorOnMainThread,
如果想延时执行代码可以用
performSelector:onThread:withObject:waitUntilDone:
11)
线程和进程的区别和联系
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
9.
在项目什么时候选择使用
GCD
,什么时候选择
NSOperation
?
gcd
是基于
c
的底层
api
,
NSOperation
属于
object-c
类。
相对于
gcd
:
1
,
NSOperation
拥有更多的函数可用,具体查看
api
。
2
,在
NSOperationQueue
中,可以建立各个
NSOperation
之间的依赖关系。
3
,有
kvo
,可以监测
operation
是否正在执行(
isExecuted
)、是否结束(
isFinished
),是否取消(
isCanceld
)。
4
,
NSOperationQueue
可以方便的管理并发、
NSOperation
之间的优先级。
gcd
主要与
block
结合使用。
项目中使用
NSOperation
的优点是
NSOperation
是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化
NSOperation
的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用
GCD
的优点是
GCD
本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而
Block
参数的使用,会是代码更为易读,建议在简单项目中使用。
1
、线程的堆栈大小
iPhone
设备上的应用程序开发也是属于嵌入式设备的开发,同样需要注意嵌入式设备开发时的几点问题,比如资源上限,处理器速度等。
iPhone
中的线程应用并不是无节制的,官方给出的资料显示
iPhone OS
下的主线程的堆栈大小是
1M
,第二个线程开始都是
512KB
。并且该值不能通过编译器开关或线程
API
函数来更改。
2
、
Autorelease
如果你什么都不考虑,在线程函数内调用
autorelease
,会出现错误
3
、子线程中描画窗口
多线程编程中普遍遵循一个原则,就是一切与
UI
相关的操作都有主线程做,子线程只负责事务,数据方面的处理。那么如果想在子线程中更新
UI
时怎么做呢?如果是在
windows
下,你会
PostMessage
一个描画更新的消息,在
iPhone
中,需要使用
performSelectorOnMainThread
委托主线程处理。
总结:
多线程能适当提高程序的执行效率,能适当提高资源利用率(
CPU
、内存利用率),但是开启线程需要占用一定的内存空间(默认情况下,主线程占用
1M
,子线程占用
512KB
),如果开启大量的线程,会占用大量的内存空间,降低程序的性能,而且线程越多,
CPU
在调度线程上的开销就越大,使用多线程程序设计更加复杂:比如线程之间的通信、多线程的数据共享
一个
iOS
程序运行后,默认会开启
1
条线程,称为“主线程”或“
UI
线程”
主线程的使用注意
:
别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响
UI
的流畅度,给用户一种“卡”的坏体验
25.
线程是什么?进程是什么?二者有什么区别和联系?
(
UI
第二十二讲
多线程编程)
线程是
CPU
独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。
26.
谈谈你对多线程开发的理解?
ios
中有几种实现多线程的方法?(
UI
第二十二讲
多线程编程)
好处:
①、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载
②、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好
缺点:
①、大量的线程降低代码的可读性,
②、更多的线程需要更多的内存空间
③、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS
有三种多线程编程的技术:
①、
NSThread(
两种创建方式
)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
②、
NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//
这个
block
语句块在子线程中执行
}
③、
Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//
耗时的操作
dispatch_async(dispatch_get_main_queue(), ^{
//
更新界面
});
});
PS:
不显示的创建线程的方法:
用
NSObject
的类方法
performSelectorInBackground:withObject:
创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
27.
线程同步和异步的区别?
IOS
中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
异步:同时去做两件或者多件事。比如边听歌边看报。
.runloop
和线程有什么关系?
总的说来,
Run loop
,正如其名,
loop
表示某种循环,和
run
放在一起就表示一直在运行着的循环。实际上,
run loop
和线程是紧密相连的,可以这样说
run loop
是为了线程而生,没有线程,它就没有存在的必要。
Run loops
是线程的基础架构部分,
Cocoa
和
CoreFundation
都提供了
run loop
对象方便配置和管理线程的
run loop
(以下都以
Cocoa
为例)。每个线程,包括程序的主线程(
main thread
)都有与之相应的
run loop
对象。
runloop
和线程的关系:主线程的
run loop
默认是启动的。
iOS
的应用程序里面,程序启动后会有一个如下的
main()
函数
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
重点是
UIApplicationMain()