pthread
pthread是一套通用的多线程API,可以在Unix/Linux/Windows等系统跨平台使用。使用C语言编写,需要程序员自己管理线程的生命周期,使用难度比极大,我们在iOS开发中几乎不适用pthread,但是我们可以来了解一下。
- 头文件
#import <pthread.h>
- 创建线程,并开启线程执行任务
pthread_create()创建一个线程
pthread_exit()终止当前线程
pthread_cancel()中断另外一个线程的运行
pthread_join() 阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init()初始化线程的属性
pthread_attr_setdetachstate()设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate() 获取脱离状态的属性
pthread_attr_destroy() 删除线程的属性
pthread_kill() 向线程发送一个信号
void * run(void *param) { // 新线程调用方法,里边为需要执行的任务{
NSLog(@"%@", [NSThread currentThread]);
return NULL;
}
int main(int argc, const char * argv[]) {
// 1. 创建线程: 定义一个pthread_t类型变量
pthread_t thread;
// 2. 开启线程: 执行任务
pthread_create(&thread, NULL, run, NULL);
// 3. 设置子线程的状态设置为 detached,该线程运行结束后会自动释放所有资源
pthread_detach(thread);
NSLog(@"%@",[NSThread currentThread]);//如果不要这一行,很可能直接return 0,线程还没调用,直接return 0了
return 0;
}
create中间有4个参数
第一个:线程对象,指向线程标识符的指针
第二个:线程属性,默认为NULL
第三个:指向函数的指针,新创建的线程从run函数地址开始运行
第四个:默认为NULL,如果需要参数,将地址传入
NSThread
NSThread是苹果官方提供的线程,使用起来比pthread更加面向对象,简单易用,可以直接操作线程对象。不过也需要程序员自己管理线程的生命周期(主要是创建)。
创建、启动线程
先创建线程,再启动线程
// 1. 创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2. 启动线程
[thread start]; // 线程一启动,就会在线程thread中执行self的run方法
// 新线程调用方法,里边为需要执行的任务
- (void)run {
NSLog(@"%@", [NSThread currentThread]);
}
创建线程后自动启动线程
// 1. 创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
// 新线程调用方法,里边为需要执行的任务
- (void)run {
NSLog(@"%@", [NSThread currentThread]);
}
隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil];
// 新线程调用方法,里边为需要执行的任务
- (void)run {
NSLog(@"%@", [NSThread currentThread]);
}
线程的相关用法
获得主线程
+ (NSThread *)mainThread;
判断是否为主线程
- (BOOL)isMainThread;
+ (BOOL)isMainThread;
获得当前线程
NSThread *current = [NSThread currentThread];
线程的名字——setter方法
- (void)setName:(NSString *)n;
线程的名字——getter方法
- (NSString *)name;
线程状态控制方法
启动方法
线程由就绪态变成运行态。当线程任务执行完毕,自动进入死亡状态
- (void)start;
阻塞(暂停)线程方法
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;//这里的参数是NSTimeInterval类型的,其值始终是以秒为单位的,直接用数字就行了
// 线程进入阻塞状态
强制停止线程
程序进入死亡状态
+ (void)exit;
线程之间的通讯
我们常常会在子线程进行耗时操作,操作结束后回到主线程刷新UI。
这就涉及到了子线程和主线程之间的通信
在主线程上执行操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector WithObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
在指定线程上执行操作
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
在当前线程上执行操作,调用NSObject的performSelector:相关方法
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
我们用的最多的就是回到主线程
现在我们学习到了
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 需要在主线程执行的代码
});
和
performSelectorOnMainThread
[self performSelectorOnMainThread:@selector(WantToGoBackMianThread:) withObject:@"1" waitUntilDone:YES];
selector:执行的方法
arg:传给方法的参数
wait:为NO,不阻塞主线程的执行
为YES,阻塞主线程的执行
- (void)WantToGoBackMianThread:(id)object{
//需要在主线程执行的代码
NSLog(@"object:%@",object);
}
线程安全
涉及到线程安全就要考虑加锁了
iOS加锁的方式有很多种
以@synchronized为例,为NSThread加锁