美文网首页IOS知识积累iOS技术点多线程
# iOS线程保活(常驻线程)

# iOS线程保活(常驻线程)

作者: Jason_YZC | 来源:发表于2019-01-03 12:33 被阅读26次

    介绍

    在日常的iOS开发中,遇到卡顿也是在所难免,一般卡顿是由于主线程处理耗时长的操作而造成线程一直在阻塞,那么我们可以去建立子线程,把耗时操作放在子线程去做,这样是完全没问题。 这样就会有一个问题,子线程处理完操作之后就会被销毁,想再处理其他事情,必须再开启新的子线程。如果想要一个子线程去持续处理事情,那么就需要这个线程一直存活在后台,在需要的时候随时可以唤醒。

    下面提供两种线程保活的方案就可以做到保活,在有任务的时候唤醒来做事情, 线程没任务时会进入休眠状态。

    方案一

    //头文件
    typedef void (^YZCPermenantThreadTask)(void);
    
    @interface YZCPermenantThread : NSObject
    
    - (void)executeTask:(YZCPermenantThreadTask)task;
    
    - (void)cancelTask;
    @end
    
    
    //==========.m文件================
    #import "YZCPermenantThread.h"
    
    #pragma mark - YZCThread
    @interface YZCThread : NSThread
    @end
    @implementation YZCThread
    -(void)dealloc {
        NSLog(@"%s",__func__);
    }
    @end
    
    #pragma mark - YZCPermenantThread
    @interface YZCPermenantThread()
    @property (nonatomic, strong) YZCThread *innerThread;
    @property (nonatomic, assign, getter=isStopped) BOOL stopped;
    @end
    
    
    @implementation YZCPermenantThread
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.stopped = NO;
            
            __weak typeof(self) weakSelf = self;
            self.innerThread = [[YZCThread alloc] initWithBlock:^{
                [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init]
                                            forMode:NSDefaultRunLoopMode];
                
                while (weakSelf && !weakSelf.isStopped) {
                    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                             beforeDate:[NSDate distantFuture]];
                }
            }];
            
            [self.innerThread start];
        }
        return self;
    }
    
    - (void)executeTask:(YZCPermenantThreadTask)task {
        if (!self.innerThread || !task) return;
        
        [self performSelector:@selector(__executeTask:) onThread:self.innerThread
                   withObject:task waitUntilDone:NO];
    }
    
    - (void)cancelTask {
        if (!self.innerThread) return;
        [self performSelector:@selector(stop) onThread:self.innerThread
                   withObject:nil waitUntilDone:YES];
    }
    
    #pragma mark - private
    - (void)stop {
        self.stopped = YES;
        CFRunLoopStop(CFRunLoopGetCurrent());
        self.innerThread = nil;
    }
    
    - (void)__executeTask:(YZCPermenantThreadTask)task {
        task();
    }
    
    

    方案二

    方案二只是核心实现不一样,其他基本一致,相比方案一去除了标记,直接使用CFRunLoop去做

    - (instancetype)init
    {
        if (self = [super init]) {
            self.innerThread = [[YZCPermenantThread alloc] initWithBlock:^{
                NSLog(@"begin----");
                
                // 创建上下文(要初始化一下结构体)
                CFRunLoopSourceContext context = {0};
                
                // 创建source
                CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
                
                // 往Runloop中添加source
                CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
                
                // 销毁source
                CFRelease(source);
                
                // 启动
                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
                
                NSLog(@"end----");
            }];
            
            [self.innerThread start];
        }
        return self;
    }
    
    

    调用

    外面调用就相对比较简单,因为上面已经封装好了

    #import "ViewController.h"
    #import "YZCPermenantThread.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) YZCPermenantThread *thread;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.thread = [[YZCPermenantThread alloc] init];
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [self.thread executeTask:^{
            NSLog(@"执行了任务:%@",[NSThread currentThread]);
        }];
    }
    

    相关文章

      网友评论

        本文标题:# iOS线程保活(常驻线程)

        本文链接:https://www.haomeiwen.com/subject/jbffrqtx.html