Runloop线程常驻
Posted 梦想家-mxj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Runloop线程常驻相关的知识,希望对你有一定的参考价值。
在ios开发过程中,有时一些花费时间比较长的操作阻塞主线程,导致界面卡顿,那么我们就会创建一个子线程,然后把这些花费时间比较长的操作放在子线程中来处理。可是当子线程中的任务执行完毕后,子线程就会被销毁掉。
如果程序中,需要经常在子线程中执行任务,频繁的创建和销毁线程,会造成资源的浪费。
这时候我们就可以使用RunLoop来让该线程长时间存活而不被销毁。
来个案例,在睡眠时,通过硬件获取数据信息(比如心电信息),开始睡眠时,创建runloop,使得子线程常驻,用于写数据到文件
睡眠结束后,退出runloop
iOS开发-RunLoop的退出方式
开启方法:
- (void)run;
- (void)runUntilDate:(NSDate *)limitDate;
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;
这三种方式无论通过哪一种方式启动runloop,如果没有一个输入源或者timer附加于runloop上,runloop就会立刻退出。
(1) 第一种方式,runloop会一直运行下去,在此期间会处理来自输入源的数据,并且会在NSDefaultRunLoopMode模式下重复调用runMode:beforeDate:方法;
(2) 第二种方式,可以设置超时时间,在超时时间到达之前,runloop会一直运行,在此期间runloop会处理来自输入源的数据,并且也会在NSDefaultRunLoopMode模式下重复调用runMode:beforeDate:方法;
(3) 第三种方式,runloop会运行一次,超时时间到达或者第一个input source被处理,则runloop就会退出。
前两种启动方式会重复调用runMode:beforeDate:方法。
二. 退出RunLoop的方式
第一种启动方式的退出方法
文档说,如果想退出runloop,不应该使用第一种启动方式来启动runloop。
如果runloop没有input sources或者附加的timer,runloop就会退出。
虽然这样可以将runloop退出,但是苹果并不建议我们这么做,因为系统内部有可能会在当前线程的runloop中添加一些输入源,所以通过手动移除input source或者timer这种方式,并不能保证runloop一定会退出。
第二种启动方式runUntilDate:
可以通过设置超时时间来退出runloop。
第三种启动方式runMode:beforeDate:
通过这种方式启动,runloop会运行一次,当超时时间到达或者第一个输入源被处理,runloop就会退出。
如果我们想控制runloop的退出时机,而不是在处理完一个输入源事件之后就退出,那么就要重复调用runMode:beforeDate:,
所以:
开始睡眠:
- (void)sleepStart{
//创建线程
NSThread *subThread = [[NSThread alloc] initWithTarget:self selector:@selector(subThreadEnter) object:nil];
[subThread setName:@"子线程"];
[subThread start];
self.ttThread = subThread;
[self performSelector:@selector(subThreadAction) onThread:self.ttThread withObject:nil waitUntilDone:NO];
}
/**
子线程启动后,启动runloop
*/
- (void)subThreadEnter
{
//给这个线程分配任务就是唤醒车这个线程的一个source RunLoop Mode就是一系列输入的source ,timer和以及observer
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
//如果注释了下面这一行,子线程中的任务并不能正常执行
[runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
NSLog(@"启动RunLoop前--%@",runLoop.currentMode);
self.runLoop = runLoop;
isLoopRunning = YES;
while (isLoopRunning){
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
};
}
}
//读写数据
- (void)readWriteData{
@autoreleasepool {
NSLog(@"%@----子线程",[NSThread currentThread]);
//写数据
NSLog(@"写入raw");
NSLog(@"写入other");
NSLog(@"写入detail");
}
}
//在获取到数据时就写入到文件
[self performSelector:@selector(readWriteData) onThread:self.ttThread withObject:nil waitUntilDone:NO];
停止睡眠时
- (void)sleepStop{
isLoopRunning = NO;
CFRunLoopStop(CFRunLoopGetCurrent());
}
这样,我们在开始睡眠的方法里使得当前子线程常驻,用于把数据信息不断地写入到文件中,当睡眠结束后,退出当前loop即可。
以上是关于Runloop线程常驻的主要内容,如果未能解决你的问题,请参考以下文章