回顾函数指针
/*
函数指针:函数的指针,本质上是一个指针,指向函数的指针
指针函数:指针的函数,代表函数的值是一个指针类型
C函数语法:
返回值类型 函数名(参数列表){
函数体;
}
*/
void test(){
NSLog(@"...");
}
/*
函数指针的语法:
返回值类型 (*函数名)(参数列表)
*/
void (*p)(); //这是一个指针变量,变量名为p,指向的是无参无返回值的函数
int (*p2)(); //这是一个指针变量,变量名为p2,指向的是无参有int类型返回值的函数
int (*p3)(int num); //这是一个指针变量,变量名为p3,指向的是一个有int类型参数和int类型返回值的函数
/*
怎么给函数指针赋值??
p = 函数名; 因为函数名就是函数地址
*/
p = test;
//void* 其实是C语言中的万能指针,相当于OC中的id
pthread的使用
- pthread开辟子线程
- 使用pthread之前,必须导入头文件
#import <pthread.h>
- 使用pthread之前,必须导入头文件
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//NSLog(@"点击里,创建前%@",[NSThread currentThread]);
//[self demo];
//C语言中以_t或者_ref结尾的都是C语言中的类型
pthread_t p;
NSString *str = @"abc";
//参数1:指向这个子线程的指针对象,要加取地址符,如果传入&p,代表这个线程由p指向了,换句话说就是通过p能找到这个子线程
//参数2:线程的属性(可以配置线程占用内存大小之类的,一般NULL就行)
//参数3:函数名(需要这个线程去执行的函数)
//参数4:函数的参数,没有参数就传NULL
//参数3和4的意思就是指:子线程执行哪个函数里面的代码并且给这个函数传入什么参数
int res = pthread_create(&p, NULL,test, (__bridge void *)(str));
//桥接:桥梁,把两种类型沟通起来
//为什么要这样?因为OC的对象目前在ARC下都是由系统管理负责回收
//但是C对象不是由系统管理的,所以把OC转C对象时,需要做桥接
//意思是告诉系统,这个对象转成C以后也由系统来管理
//返回值是int类型,代表线程是否创建成功
//返回0代表成功,返回其他代表失败
//返回值其实是一个错误标识,只有0代表没有错误,如果为其他数字代表不同的错误
//比如1代表xxx错误,比如2代表yyy错误
if(res == 0){
NSLog(@"创建成功");
}else{
NSLog(@"创建失败");
}
//NSLog(@"点击里,创建后%@",[NSThread currentThread]);
}
void *test(void *num){
NSString *str = (__bridge NSString *)(num);
//NSLog(@"%p",num);
// NSLog(@"test里%@",[NSThread currentThread]);
NSLog(@"%@",str);
return NULL;
}
-(void)demo{
//[NSThread currentThread]可以打印出当前线程对象的信息
//也就是可以看到当前代码是由哪个线程执行的
/*
是不是主线程看number,number==1才是主线程,number!=1是子线程
*/
NSLog(@"demo方法%@",[NSThread currentThread]);
}
NSThread的使用
三种创建方式
-
构造方法方式
//NSThread 是一个线程对象 //参数1和参数2:开启的子线程要调用哪个对象的哪个方法 //参数3:给这个方法的参数,有就传没有就传nil NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"hello"]; //用这种方式创建,一定要start [th1 start];PS:需要start !!!
可以在线程执行的方法外也访问到这个线程对象 -
类方法方式
//参数1:哪个方法 //参数2:哪个对象的 //参数3:方法的参数 //这个方法会创建一个新的线程来执行某个的对象的某个方法 [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"hello"];不需要start
在调用的方法外访问不到线程对象 -
分类方式(NSObject的分类)
//参数1:调用哪个方法 //参数2:方法的参数 [self performSelectorInBackground:@selector(demo:) withObject:@"abc"];也不需要start
调用的方法外访问不到线程对象
常用属性
- name(线程名称)
- stackSize(栈区大小)
- 默认情况下,无论是主线程还是子线程,栈区大小都是 512K(设置比512小的值无效)
- 栈区大小可以设置
[NSThread currentThread].stackSize = 1024 * 1024; - 必须是 4KB 的倍数
- isMainTread(是否主线程)
- threadPriority(线程优先级)
- 优先级,是一个浮点数,取值范围从 0~1.0
- 1.0最高,0.0最低
- 默认优先级是 0.5
- 优先级高只是保证 CPU 调度的可能性会高,不是先调用完成优先级高的进程
- qualityOfService(服务质量-iOS8.0推出)
- NSQualityOfServiceUserInteractive - 用户交互,例如绘图或者处理用户事件
- NSQualityOfServiceUserInitiated - 用户需要
- NSQualityOfServiceUtility - 实用工具,用户不需要立即得到结果
- NSQualityOfServiceBackground - 后台
- NSQualityOfServiceDefault - 默认,介于用户需要和实用工具之间