进程与线程的关系:
进程:是指在系统中正在运行的一个应用程序。进程想要执行任务必须的有线程,至少要有一条线程,进程启动默认会开启一条线程,这条线程称之为主线程或UI线程。
线程是进程的基本单元,一个进程的所有任务都在线程中执行
地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间
资源:同一进程内的线程共享本进程的资源如内存、I/o、CPU 等,但是进程之间是独立的
1、一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程死掉,所以多进程比多线程健壮
2、进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程,同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
3、执行过程:每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口,但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
4、线程是处理器调度的基本单位,但是进程不是
5、线程没有地址空间,线程包含在进程地址空间中
多线程的意义:
优点:
1、能适当提高程序的执行效率
2、能适当提高资源的利用率(cpu,内存)
3、线程上的任务执行完成后,线程会自动销毁
缺点:
1、开启线程会占用一定的内存空间(默认情况下,每一个线程都占512kb)
2、如果开启大量的线程,会占用大量的内存空间、降低程序的性能
3、线程越多,cpu在调用线程上开销就越大
4、线程设计更加复杂,比如线程间的通信、多线程的数据共享
多线程的技术方案:
图(1)创建NSThread线程:
图(2)取消线程:[[NSThread currentThread] cancel];
强制退出线程:[NSThread exit];
判断线程是否取消:[NSThread currentThread].isCancelled
判断线程是否完成:[NSThread currentThread].finished
// 阻塞线程: [NSThread sleepForTimeInterval:1];
detach 分离,不需要启动,直接分离出新的线程执行:
图(3)隐式`的多线程调用方法,没有thread,也没有 start:
图(4)线程下载,刷新uI必须回到主线程:
图(5)C和OC的桥接:
__bridge只做类型转换,但是不修改对象(内存)管理权
__bridge_retained(也可以使用‘CFBridgingRetain’)将OC对象转换为Core Foundation的对象,同时将对象(内存)的管理权限交给开发者,后面需要使用CFRelease或者相关方法来释放对象
__bridge_transfer(也可以使用‘CFBridgingRelease’)将Core Foundation的对象转换为OC的对象,同时将对象(内存)的管理权限交给ARC
线程的生命周期:
图(6)线程池:
图(7)饱和策略:
1、AbortPolicy直接抛出RejectedExecutionExeception异常来阻止系统正常运行
2、CallerRunsPolicy 将任务回退到调用者
3、DisOldestPolicy丢掉等待最久的任务
4、DisCardPolicy 直接丢弃任务
atomic与nonatomic的区别:
1、nonatomic:非原子属性,非线程安全,适合线程小的安全设备
2、atomic:原子属性(线程安全),针对多线程设计的,保证同一时间只有一个线程能够写入,本身就用拥有一个锁(自旋锁),单写多读:单个线程写入,多个线程可以读取
ios开发建议:所有的属性都声明为nonatomic,尽量避免多线程抢夺同一块资源,尽量加锁,资源抢夺的业务逻辑放在服务器端处理,减少客户端的压力
线程和runloop的关系:
1、runloop与线程是一一对应的,一个Runloop对应一个核心的线程
2、runloop是用来管理线程的,当线程的runloop被开启过后,线程会执行完任务过后进入休眠状态,有了任务就会被唤醒去执行任务
3、runloop在第一次获取时被创建,在线程结束时销毁
4、对于主线程,runloop在程序启动的时候就默认创建好了
5、对于子线程,runloop是懒加载的,只有当我们使用的时候的才会创建,所以在子线程用定时器的时候需要创建runloop
网友评论