本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。
本文相关目录:
==================== 所属文集:4.0 多线程 ====================
4.1 多线程基础->1.0 进程 & 线程
······················ 2.0 多线程简介
4.2 pthread
4.3 NSThread->1.0 创建线程
····················· 2.0 线程属性
····················· 3.0 线程状态/线程生命周期
····················· 4.0 多线程安全隐患
····················· 5.0 线程间通讯和常用方法
4.4 GCD->1.0 GCD简介和使用
·············· 2.0 线程间的通信
·············· 3.0 其他用法
·············· 4.0 GCD 的定时器事件
4.5 NSOperation->1.0 NSOperation简介
························ 2.0 NSOperationQueue
························ 3.0 线程间通信
························ 4.0 自定义NSOperation
4.6 RunLoop - 运行循环
===================== 所属文集:4.0 多线程 =====================
线程状态
- 新建状态
- 就绪状态/启动状态 : 线程在可调度线程池中
- 运行状态
- 阻塞状态/暂停线程 : 线程不在可调度线程池中,但是仍然存在内存中,只是不可用
- 死亡状态 : 线程不在内存中
3.1 新建状态
(1)新建状态 : 实例化线程对象
说明:创建线程有多种方式,这里不做过多的介绍
NSThread *thread =[[NSThread alloc] initWithTarget:self
selector:@selector(run)
object:nil];
3.2 就绪状态 / 启动线程
(2)就绪状态 / 启动线程: ( 进入就绪状态 ->运行状态。当线程任务执行完毕,自动进入死亡状态 )
线程开启 : 线程进入可调度线程池
- 向线程对象发送 start 消息,线程对象被加入可调度线程池等待 CPU 调度
- detachNewThreadSelector 方法和 performSelectorInBackground 方法会直接实例化一个线程对象并加入可调度线程池
[thread start];
3.3 运行状态
(3)运行状态:
- CPU 负责调度可调度线程池中线程的执行
- 线程执行完成之前(死亡之前),状态可能会在就绪和运行之间来回切换
- 就绪和运行之间的状态变化由 CPU 负责,程序员不能干预
- 当 CPU 调度当前线程 , 进入运行状态
- 当 CPU 调度其他线程 , 进入就绪状态
3.4 阻塞状态 / 暂停线程
(4)阻塞状态 / 暂停线程 : 当满足某个预定条件时,可以使用休眠或锁阻塞线程执行
方法执行过程,符合某一条件时,可以利用 sleep 方法让线程进入 阻塞 状态
sleepForTimeInterval: //休眠指定时长 (从现在起睡多少秒)
sleepUntilDate: //休眠到指定日期 (从现在起睡到指定的日期)
@synchronized(self) { } //互斥锁
(1)阻塞2秒
[NSThread sleepForTimeInterval:2]; // 阻塞状态
(2)以当前时间为基准阻塞4秒
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:4.0]; //从现在开始多少秒
[NSThread sleepUntilDate:date]; //睡眠多少秒
未阻塞前:
阻塞后 ——> 变为就绪状态
线程处理阻塞状态时在内存中的表现情况:线程被移出可调度线程池,此时不可调度
3.5 死亡状态
(5)死亡状态 (一旦线程停止或死亡了,就不能再次开启任务 , 后续的所有代码都不会被执行 )
(1) 正常死亡
- 线程执行完毕
(2) 非正常死亡
- (自杀) 当满足某个条件后,在线程内部自己中止执行
- (被逼着死亡) 当满足某个条件后,在主线程给其它线程打个死亡标记,让子线程自行了断.
注意:在终止线程之前,应该注意释放之前分配的对象!
[NSThread exit]; //终止线程.强制停止线程
内存情况 : 线程死亡后,线程对象从内存中移除
代码示例
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 1.在主线程中创建一个子线程(实例化线程对象) ---> 新建状态
NSThread *Th =
[[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2.将 Th 线程加入到可调度线程池,等待CPU调度--->就绪状态
[Th start];
// 3.让主线程阻塞,让当前线程(主线程)休眠
[NSThread sleepForTimeInterval:1.0];
// 4.在主线程给 Th 线程打死亡标签
[Th cancel]; //只是打了个标签,并没有执行,需要在子线程中
}
// Th 线程---> 运行状态
- (void)run {
NSThread *huThread = [NSThread currentThread];
CGMutablePathRef path = CGPathCreateMutable();
for (int i = 0; i < 30; i++) {
if ([huThread isCancelled]) {
NSLog(@"good bye1");
return; // --->非正常死亡(被逼着死亡)
}
if (i == 5) {
[NSThread sleepForTimeInterval:3.0]; //--->huThread阻塞状态3秒
// [NSThread sleepUntilDate:[NSDate distantFuture]]; // 睡到遥远的未来
// [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; //线程睡到从现在开始后的2秒为止
}
if ([huThread isCancelled]) {
NSLog(@"good bye2");
return;
}
if (i == 20) {
//清空资源
CGPathRelease(path);
//在调用下面方法之前,必须清空资源 非正常死亡--自杀(退出线程)
[NSThread exit];
}
if ([huThread isCancelled]) {
NSLog(@"good bye3");
return;
}
NSLog(@"%d", i);
}
} //--->huThread死亡状态 (正常死亡状态)
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
本文源码 Demo 详见 Github
https://github.com/shorfng/iOS_4.0_multithreading.git
作者:蓝田(Loto)
出处:
如果你觉得本篇文章对你有所帮助,请点击文章末尾下方“喜欢”
如有疑问,请通过以下方式交流:
① 评论区回复
② 微信(加好友请注明“+称呼”)
③发送邮件
至 [email protected]
本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。