一. 创建线程的3种方法
1.alloc init
- (void)threadDemo1
{
// 这一句只是 分配内存和初始化
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo1:)object:@"Thread"];
// 这一句才是启动线程
[thread start];
}
2.detachNewThreadSelector
- (void)threadDemo2
{
[NSThread detachNewThreadSelector:@selector(demo1:) toTarget:self withObject:@"detach"];
}
3.performSelectorInBackground
- (void)threadDemo3
{
[self performSelectorInBackground:@selector(demo1:) withObject:@"background"];
}
performSelectorInBackground 是NSObject的一个分类方法,意味着所有的NSObject都可以使用该方法,在其他线程执行方法!
特点:没有thread 字眼,一旦指定,就会立即在后台线程执行selector 方法,是隐式的多线程方法,这种方法在使用时更加灵活!
例如:
一个 Person 类继承自NSObject,有个方法 loadData很耗时,在viewController里实例化一个Person * P,可以这样调用:
[PperformSelectorInBackground:@selector(loadData)withObject:nil];
二、NSLog是专门用来调试的,性能非常不好,在商业软件中,要尽量去掉
三、
[NSThread currentThread],当前线程对象,可以在所有的多线程技术中使用,通常用来判断是否在主线程
输出的信息中,关注 number
Number == 1 说明是主线程
Number != 1 说明不是主线程
四、线程状态
// 线程状态的demo
- (void)threadStatusDemo
{
// 实例化线程对象(新建)
NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(threadStatus)object:nil];
// 就绪
[t start];
}
- (void)threadStatus
{
NSLog(@"睡会儿");
// 阻塞
// sleep 是类方法,会直接休眠当前线程
[NSThread sleepForTimeInterval:2.0];
for (int i = 0; i < 10; i++)
{
if (i == 4)
{
NSLog(@"再睡会儿");
// 线程执行中,满足某个条件时,再次休眠
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
}
NSLog(@"%@, %d", [NSThread currentThread], i);
if (i == 8)
{
// 终止
// 一旦终止,后续所有的代码都不会被执行,注意:在终止线程之前,应该注意释放之前分配的对象,如果是ARC 开发,需要注意,清理C语言框架创建的对象,否则会出现内存泄漏
[NSThread exit];
}
}
NSLog(@"能来吗?");
}
五、线程属性
name 、isMainThread
// 线程属性
- (void)threadPropertyDemo
{
NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(threadProperty)object:nil];
// 属性1. name:在大的商业项目中,通常希望程序崩溃的时候,能够获取到程序准确执行所在的线程
t.name = @"Thread A";
[t start];
}
- (void)threadProperty
{
for (int i = 0; i < 2; i++)
{
NSLog(@"%@, %d", [NSThread currentThread], i);
}
// 属性2. 判断是否是主线程
if (![NSThread isMainThread])
{
// 模拟崩溃
NSMutableArray *array = [NSMutableArray array];
[array addObject:nil];
}
}