ios线程第二发: NSThread(附录1)
2015-01-31 00:08
267 查看
NSThread:
1.创建、启动线程
1>手动启动的线程(经常使用)
// 线程一启动,就会在线程thread中执行self的run方法
NSThread *thread = [[[NSThread
alloc] initWithTarget:self
selector:@selector(run)
object:nil]
start];
2>创建线程后自动启动线程
[NSThread
detachNewThreadSelector:@selector(run)
toTarget:self
withObject:nil];
3>隐式创建并启动线程
[self
performSelectorInBackground:@selector(run)
withObject:nil]
以上两种创建方法优缺点:创建快速简单,但是不能进行详细设置
(1)常用属性:
start:(将线程对象加入可调度线程池等待CPU调度)
线程的名字:name(可以自己设置)在商业级应用程序中,通常希望程序崩溃的时候,能够知道准确执行的线程!更容易排错
线程优先级:threadPriority默认0.5 取值范围是0.0—1.0 优先级高的调度频率比较高,不要进行修改优先级操作, 修改优先级有一个隐患->优先级翻转
线程的优先级:优先级高的任务只是表示 CPU 调度的频率高!
误区:优先级高的任务会先执行完!
状态属性(只读):
isExecuting 是否在执行
isFinished 是否完成
isCancelled 是否取消
线程大小:stackSize(默认线程都占用512kb,以前主线程1m, 子线程512k)
可以自己设置,设置的时候是4k 得倍数
取消线程: cancle 可以在外部终止线程序执行,在执行方法中需要增加 isCancelled 判断,如果isCancelled == YES 直接返回
主线程相关用法
// 获得当前线程,开发中常用于调试,适用于所有线程技术number==1 表示主线程,其它为后台线程
+ (NSThread *)currentThread;
+ (NSThread *)mainThread; // 获得主线程
- (BOOL)isMainThread; // 是否为主线程
+ (BOOL)isMainThread; // 是否为主线程
+isMultiThreaded / / 是否为多线程
2.线程的状态
1>新建:实例化线程对象
2>就绪
(1)向线程发送 start 消息,线程对象被加入”可调度线程池”等待 cpu 调度
(2)detach 和 performSelectorInBackground 方法会直接实例化一个线程池对象并加入”可调度线程池”
3>运行
(1)cpu 负责调度”可调度线程池”中线程的执行
(2)线程执行完成之前,状态可能会在就绪和运行之间来回切换
(3)就绪和运行之间的状态变化由 cpu 负责,程序员不能干预
4>阻塞
(1)当满足某个预定条件时,可以使用休眠或者阻塞线程的执行: sleepFormTimeInterval,sleepUntilDate,@synchronized(self)
(2)线程对象进入阻塞状态后,会被从”可调度线程池”中移除, cpu 不再调度
5>死亡
(1)死亡方式: 正常死亡 —> 线程执行完毕
非正常死亡 —> 线程内死亡: [NSThread exit]
强制终止,后续代码不会执行
线程外死亡:[NSThread acncell] 通知线程对象取消(在执行方法中需要增加 isCancelled 判断,如果 isCancell == YES ,直接返回)
(2)死亡后线程对象的 isFinish 属性为 YES
(3)如果发送cancell 消息,线程对象的 isCancell 属性为 YES
(4)死亡后 stackSize == 0 ,内存空间被释放
注意:一旦线程被强行终止了,后续所有代码都不会再继续执行!
没有给线程机会释放执行过程中申请的资源
exit 方法会直接终止线程,要调用之前,需要考虑释放对象
ARC 中通常不用考虑,如果涉及到 c 语言混编,如果分配了 c 语言的对象,在 exit 之前,一定记住 release!
3.多线程的安全隐患解决 —— 互斥锁:
1>安全隐患:(当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题)
2>互斥锁/同步锁:
(保证同一时间内,只有一条线程执行)(synchronized)
3>互斥锁使用格式:
@synchronized(锁对象) {
// 需要锁定的代码 }
注意:
互斥锁会降低性能,
互斥锁锁定代码的范围,应该尽量的小
使用互斥锁会影响并发的目的
xcode 没有智能提示,因为互斥锁性能不好,苹果不建议使用
synchronized(self) self 是一个能够加锁的 NSObject 对象,而且要保证所有线程都能共同访问到该对象
一般情况而言, self 最方便使用加锁对象,如果程序只有一个地方涉及到加锁,绝大多数可以考虑使用 self
4>原子属性(atomic)
(1)能够实现”单写多读”的数据保护:
同一时间只允许一个线程修改属性值,但是允许多个线程读取
多线程读取数据的时候有可能出现脏数据, — 读取的数据可能会不正确
(2)原子属性是默认属性,如果不考虑线程安全,要指定
(3)原子属性:nonatomic 和非原子属性: atomic
原子属性 —> 默认属性: atomic
原子属性是能够保证”线程安全”的属性,原子属性内部也有一把锁”自旋锁"
自旋锁 和 synchronized
A. 共同点:保证同一时间只有一个线程执行锁定范围内的代码
B. 不同:
互斥锁: 当发现要执行的代码被其他线程锁定之后,线程会进入休眠状态,等待解锁之后,线程会被再次唤醒.
自旋锁: 当发现要执行的代码被其他线程锁定之后,会以死循环的方式,监听是否解锁,一旦解锁,立即执行,执行性能高,适合于锁定非常短的代码
5>线程安全:
就是在多个线程同时对一个资源进行读写操作时,同样能够保证结果是正确的.
要实现线程安全,必须要使用锁
只要使用锁,就会降低性能
UI 线程——主线程
主线程又被称为 UI 线程,UIKIt 中几乎所有的控件都不是线程安全的,因此需要在主线程上更新 UI.
1.创建、启动线程
1>手动启动的线程(经常使用)
// 线程一启动,就会在线程thread中执行self的run方法
NSThread *thread = [[[NSThread
alloc] initWithTarget:self
selector:@selector(run)
object:nil]
start];
2>创建线程后自动启动线程
[NSThread
detachNewThreadSelector:@selector(run)
toTarget:self
withObject:nil];
3>隐式创建并启动线程
[self
performSelectorInBackground:@selector(run)
withObject:nil]
以上两种创建方法优缺点:创建快速简单,但是不能进行详细设置
(1)常用属性:
start:(将线程对象加入可调度线程池等待CPU调度)
线程的名字:name(可以自己设置)在商业级应用程序中,通常希望程序崩溃的时候,能够知道准确执行的线程!更容易排错
线程优先级:threadPriority默认0.5 取值范围是0.0—1.0 优先级高的调度频率比较高,不要进行修改优先级操作, 修改优先级有一个隐患->优先级翻转
线程的优先级:优先级高的任务只是表示 CPU 调度的频率高!
误区:优先级高的任务会先执行完!
状态属性(只读):
isExecuting 是否在执行
isFinished 是否完成
isCancelled 是否取消
线程大小:stackSize(默认线程都占用512kb,以前主线程1m, 子线程512k)
可以自己设置,设置的时候是4k 得倍数
取消线程: cancle 可以在外部终止线程序执行,在执行方法中需要增加 isCancelled 判断,如果isCancelled == YES 直接返回
主线程相关用法
// 获得当前线程,开发中常用于调试,适用于所有线程技术number==1 表示主线程,其它为后台线程
+ (NSThread *)currentThread;
+ (NSThread *)mainThread; // 获得主线程
- (BOOL)isMainThread; // 是否为主线程
+ (BOOL)isMainThread; // 是否为主线程
+isMultiThreaded / / 是否为多线程
2.线程的状态
1>新建:实例化线程对象
2>就绪
(1)向线程发送 start 消息,线程对象被加入”可调度线程池”等待 cpu 调度
(2)detach 和 performSelectorInBackground 方法会直接实例化一个线程池对象并加入”可调度线程池”
3>运行
(1)cpu 负责调度”可调度线程池”中线程的执行
(2)线程执行完成之前,状态可能会在就绪和运行之间来回切换
(3)就绪和运行之间的状态变化由 cpu 负责,程序员不能干预
4>阻塞
(1)当满足某个预定条件时,可以使用休眠或者阻塞线程的执行: sleepFormTimeInterval,sleepUntilDate,@synchronized(self)
(2)线程对象进入阻塞状态后,会被从”可调度线程池”中移除, cpu 不再调度
5>死亡
(1)死亡方式: 正常死亡 —> 线程执行完毕
非正常死亡 —> 线程内死亡: [NSThread exit]
强制终止,后续代码不会执行
线程外死亡:[NSThread acncell] 通知线程对象取消(在执行方法中需要增加 isCancelled 判断,如果 isCancell == YES ,直接返回)
(2)死亡后线程对象的 isFinish 属性为 YES
(3)如果发送cancell 消息,线程对象的 isCancell 属性为 YES
(4)死亡后 stackSize == 0 ,内存空间被释放
注意:一旦线程被强行终止了,后续所有代码都不会再继续执行!
没有给线程机会释放执行过程中申请的资源
exit 方法会直接终止线程,要调用之前,需要考虑释放对象
ARC 中通常不用考虑,如果涉及到 c 语言混编,如果分配了 c 语言的对象,在 exit 之前,一定记住 release!
3.多线程的安全隐患解决 —— 互斥锁:
1>安全隐患:(当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题)
2>互斥锁/同步锁:
(保证同一时间内,只有一条线程执行)(synchronized)
3>互斥锁使用格式:
@synchronized(锁对象) {
// 需要锁定的代码 }
注意:
互斥锁会降低性能,
互斥锁锁定代码的范围,应该尽量的小
使用互斥锁会影响并发的目的
xcode 没有智能提示,因为互斥锁性能不好,苹果不建议使用
synchronized(self) self 是一个能够加锁的 NSObject 对象,而且要保证所有线程都能共同访问到该对象
一般情况而言, self 最方便使用加锁对象,如果程序只有一个地方涉及到加锁,绝大多数可以考虑使用 self
4>原子属性(atomic)
(1)能够实现”单写多读”的数据保护:
同一时间只允许一个线程修改属性值,但是允许多个线程读取
多线程读取数据的时候有可能出现脏数据, — 读取的数据可能会不正确
(2)原子属性是默认属性,如果不考虑线程安全,要指定
(3)原子属性:nonatomic 和非原子属性: atomic
原子属性 —> 默认属性: atomic
原子属性是能够保证”线程安全”的属性,原子属性内部也有一把锁”自旋锁"
自旋锁 和 synchronized
A. 共同点:保证同一时间只有一个线程执行锁定范围内的代码
B. 不同:
互斥锁: 当发现要执行的代码被其他线程锁定之后,线程会进入休眠状态,等待解锁之后,线程会被再次唤醒.
自旋锁: 当发现要执行的代码被其他线程锁定之后,会以死循环的方式,监听是否解锁,一旦解锁,立即执行,执行性能高,适合于锁定非常短的代码
5>线程安全:
就是在多个线程同时对一个资源进行读写操作时,同样能够保证结果是正确的.
要实现线程安全,必须要使用锁
只要使用锁,就会降低性能
UI 线程——主线程
主线程又被称为 UI 线程,UIKIt 中几乎所有的控件都不是线程安全的,因此需要在主线程上更新 UI.
相关文章推荐
- iOS多线程_05_线程间通信NSThread/GCD
- iOS NSThread 的三种创建线程的方法 非常简单好用
- iOS-多线程(NSThread-线程之间的通信)
- IOS线程数据篇2之多线程:NSThread NSOperation GCD(一)
- ios之NSThread开辟子线程方法
- iOS-多线程(NSThread-线程的状态)
- IOS NSThread 线程间通信
- iOS -- 线程 还有待补全--(关于线程死锁,解决办法等。。)(NSThread、NSOperation、GCD) -- ASI/AFNetWork
- iOS 开发 多线程详解之NSThread异步线程下载网络图片
- iOS学习总结之多线程编程(NSThread)-线程的状态
- iOS 线程 NSCondition NSThread
- ios线程第二发: GCD(附录2)
- iOS - 线程(NSThread / NSOperation / GCD)
- iOS线程之NSThread
- iOS-开辟子线程(NSThread、NSOperationQueue、GCD)
- iOS NSThreadGCD 线程与队列(二)
- iOS NSthread & Thread 开启线程的几种方式
- iOS--线程间通讯NSThread--04
- iOS开发之多线程(NSThread创建线程)
- IOS线程数据篇3之多线程:NSThread NSOperation GCD(二)