线程创建出来就处于等待状态(有或无任务),想用它的时候就用它执行任务,不想用的时候就处于等待状态。
- 聊天发送语音消息,可能会专门开一个子线程来处理;
- 在后台记录用户的停留时间或某个按钮点击次数,这些用主线程做可能不太方便,可能会开启一个子线程后台默默收集;
实现一个常驻线程
- 为当前线程开启一个
Runloop - 向该
Runloop中添加一个Port/Source等维持 Runloop 的事件循环 - 启动该
Runloop
#import "ViewController.h"@interface ViewController ()@property(nonatomic,strong)NSThread *thread;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];}-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{// 创建子线程并开启NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(show) object:nil];self.thread = thread;[thread start];}-(void)show{// 注意:打印方法一定要在RunLoop创建开始运行之前,如果在RunLoop跑起来之后打印,RunLoop先运行起来,已经在跑圈了就出不来了,进入死循环也就无法执行后面的操作了。// 但是此时点击Button还是有操作的,因为Button是在RunLoop跑起来之后加入到子线程的,当Button加入到子线程RunLoop就会跑起来NSLog(@"%s",__func__);// 1.创建子线程相关的RunLoop,在子线程中创建即可,并且RunLoop中要至少有一个Timer 或 一个Source 保证RunLoop不会因为空转而退出,因此在创建的时候直接加入// 添加Source [NSMachPort port] 添加一个端口[[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];// 添加一个TimerNSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];//创建监听者CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {switch (activity) {case kCFRunLoopEntry:NSLog(@"RunLoop进入");break;case kCFRunLoopBeforeTimers:NSLog(@"RunLoop要处理Timers了");break;case kCFRunLoopBeforeSources:NSLog(@"RunLoop要处理Sources了");break;case kCFRunLoopBeforeWaiting:NSLog(@"RunLoop要休息了");break;case kCFRunLoopAfterWaiting:NSLog(@"RunLoop醒来了");break;case kCFRunLoopExit:NSLog(@"RunLoop退出了");break;default:break;}});// 给RunLoop添加监听者CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);// 2.子线程需要开启RunLoop[[NSRunLoop currentRunLoop]run];CFRelease(observer);}- (IBAction)btnClick:(id)sender {[self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];}-(void)test{NSLog(@"%@",[NSThread currentThread]);}@end
注意:创建子线程相关的RunLoop,在子线程中创建即可,并且RunLoop中要至少有一个Timer 或 一个Source 保证RunLoop不会因为空转而退出,因此在创建的时候直接加入,如果没有加入Timer或者Source,或者只加入一个监听者,运行程序会崩溃
