NSThread类是实现多线程的一种方案,也是实现多线程最简单的方式。
1、线程的创建和启动
在iOS开发中,通过创建一个NSThread类的实例作为一个线程,一个线程就是一个NSThread对象。要想使用NSThread类创建线程,有3种方法,具体如下所示:
在上述代码中,这三种方法都是将target对象或者其所在对象的selector方法转化为线程的执行者。其中selector方法最多可以接收一个参数,而object后面对应的就是它接收的参数。
//1、创建新的线程
-(instancetype)initWithTarget:(id)target selector:(SEL)selectorobject:(id)argument
//2、创建线程后自动启动线程
+(void)detachNewThreadSelector:(SEL)selector toTarget:(id)targetwithObject:(id)argument;
//3、隐式创建线程
-(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;
这三种方法中:
第一种方法是对象方法,返回一个NSThread对象,并可以对该对象进行详细的设置,必须通过调用start 方法来启动线程;
第二种方法是类方法,创建对象成功之后就会直接启动线程,前两个方法没有本质的区别;
第三种方法属于隐式创建,主要在后台创建线程。
除了以上三种方法,NSThread类还提供了两个方法用于获取当前线程和主线程,具体的定义格式如下:
//获取当前线程
+(NSThread *)currentThread;
//获得主线程
+(NSThread *)mainThread;
接下来通过一个示例展示3种方法的使用:
(1)新建一个SingleViewApplication应用,名称为01-NSThreadDemo;
(2)进入Main.StoryBoard,从对象库添加一个Button和一个Text View,其中,Button用于响应用户单击事件,而Text View用于测试线程的阻塞,界面如下:
(3)将StoryBoard上面的Button通过拖拽的方式,在ViewController.m中进行声明以响应btnClick:消息。通过三种创建线程的方法创建线程,这三种方法分别被封装在threadCreate1、threadCreate2、threadCreate3三个方法中,之后依次在bthClick:中被调用,代码如下:
#import "ViewController.h"
@interface ViewController ()
//按钮被单击
//声明按钮被单击函数
- (IBAction)btnClick:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnClick:(id)sender {
//获取当前线程
NSThread *current=[NSThread currentThread];
NSLog(@"btnClick--%@--current",current);
//获取主线程
NSThread *main=[NSThread mainThread];
NSLog(@"btnClick--%@--main",main);
[self threadCreate1];
}
-(void)run:(NSString*)param
{
//获取当前线程
NSThread *current=[NSThread currentThread];
for(int i=0;i<10;i++){
NSLog(@"%@---run---%@",current,param);
}
}
//第一种创建方式
-(void)threadCreate1{
NSThread *threadA=[[NSThread alloc] initWithTarget:self
selector:@selector(run:) object:@"哈哈"];
threadA.name=@"线程A";
//开启线程A
[threadA start];
NSThread *threadB=[[NSThread alloc] initWithTarget:self
selector:@selector(run:) object:@"哈哈"];
threadB.name = @"线程B";
//开启线程B
[threadB start];
}
//第二种创建方式
-(void)threadCreate2
{
[NSThread detachNewThreadSelector:@selector(run:)
toTarget:self withObject:@"我是参数"];
}
//隐式创建线程且启动,在后台线程中执行,也就是在子线程中执行
-(void)threadCreate3
{
[self performSelectorInBackground:@selector(run:) withObject:@"参数3"];
}
//测试阻塞线程
-(void)test
{
NSLog(@"%@",[NSThread currentThread]);
for(int i;i<10000;i++)
{
NSLog(@"__________%d",i);
}
}
@end
直接运行则调用了第一种线程创建方法,运行结果如图:
将btnClick函数中的[selfthreadCreate1];修改为[self threadCreate2]; 之后,则调用了第二种线程创建方法,运行结果如下:
将btnClick函数中的[self threadCreate2];修改为[self threadCreate3]; 之后,则调用了第三种线程创建方法,运行结果如下:
将btnClick函数中的[self threadCreate2];修改为[self test]; 之后,则用于测试线程的阻塞情况,运行结果如下: