iOS中的线程保活

iOS开发中我们经常使用异步线程处理耗时任务,在一些场景中,如果频繁地创建和销毁线程的话,会带来额外的开销,所以有时需要对线程保活。iOS中runloop是事件循环,它可以持续地等待和处理用户交互和UI渲染,每一个线程都对应着一个runloop。对于主线程来说,runloop是默认开启的,而对于子线程来说,runloop是默认关闭的。可以通过开启runloop来做线程保活。

这里有个线程保活的例子,在ViewController页面可见的时候创建一个线程并且保活,在页面消失的时候销毁线程,停止runloop。页面可见和不可见的状态可能是频繁触发的,所以这里的线程保活仅仅是示例,在实际应用中可以根据情况减少线程创建和销毁的次数。

在ViewController类中,增加NSTread类型的属性,增加keepRunning代表线程的运行状态

@interface SecondViewController ()

@property (nonatomic, strong) NSThread *thread;
@property (nonatomic, assign) BOOL keepRunning;

@end

在viewWillAppear中创建线程,使用[NSRunLoop currentRunLoop];获取当前的runloop,使用NSPort为runloop增加source以便runloop运行。runloop运行的时候必须使用-runMode:beforeDate:这个方法,只有这个方法运行的runloop是可以停止的。-runUntilDate:和run方法运行的runloop不可以停止,因为runUntilDate:方法运行runloop的时候,它会在循环中持续地调用-runMode:beforeDate:导致runloop无法使用stop方法停止运行。

- (void)viewWillAppear:(BOOL)animated
{
    
    
    [super viewWillAppear:animated];
    self.keepRunning = YES;
    __weak typeof(self) weakSelf = self;
    self.thread = [[NSThread alloc] initWithBlock:^{
    
    
        NSRunLoop *theRL = [NSRunLoop currentRunLoop];
        [theRL addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        while (weakSelf.keepRunning){
    
    
            [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            NSLog(@"test");
        }
    }];
    [self.thread start];
}

在viewWillDisappear中增加代码

- (void)viewWillDisappear:(BOOL)animated
{
    
    
    [super viewWillDisappear:animated];
    [self performSelector:@selector(invalidateThread) onThread:self.thread withObject:nil waitUntilDone:YES];
}

- (void)invalidateThread
{
    
    
    self.keepRunning = NO;
    CFRunLoopRef rl = CFRunLoopGetCurrent();
    CFRunLoopStop(rl);
}

invalidateThread方法用于停止runloop,runloop终止后,线程也会释放。

猜你喜欢

转载自blog.csdn.net/u011608357/article/details/128163979