ios 之 常驻线程

741 阅读2分钟

常驻线程

线程我们用来处理任务,但是一个线程只能同时处理一个任务,且在执行完任务后,就退出了.如果在执行下一个任务就需要重新开启一个线程,这样会不停的消耗CPU资源.基于此,我们就谈到了常驻线程这个概念.说到常驻线程,RunLoop就是一个常驻线程,它的存在,得以让程序随时处理事件,如果没有事件处理他会休眠.

下面我们就开始自己动手创建我们自己的常驻线程:

一:在默认全局常驻线程中执行操作(只要调用,默认线程及创建且不会销毁)

+ (void)excuteTask:(SXLivingThreadTask)task{
    if (!task) {
        return;
    }
    if (!sx_defaultThread) {
        void(^createThreadBlock)(void) = ^{
            NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop];
            [currentRunloop addPort:[NSPort new] forMode:NSDefaultRunLoopMode];
            [[NSRunLoop currentRunLoop] run];
            while (1) {
                [currentRunloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            }
        };
        sx_defaultThread = [[NSThread alloc] initWithBlock:createThreadBlock];
        [sx_defaultThread start];
    }
    [self performSelector:@selector(class_taskMethod:) onThread:sx_defaultThread withObject:task waitUntilDone:NO];
}
+ (void)class_taskMethod:(SXLivingThreadTask)task{
    task();
}

二:自定义全局常驻线程中执行操作,创建了也是不会销毁的

+ (void)excuteTask:(SXLivingThreadTask)task identify:(NSString *)identify{

    if (!task || !identify || identify.length == 0) {
        return;
    }
    if (!sx_threadDictM) {
        sx_threadDictM = [NSMutableDictionary dictionary];
    }
    
    NSThread *threadByIdentity = [sx_threadDictM objectForKey:identify];
    if (!threadByIdentity) {
        void(^createThreadBlock)(void) = ^{
            CFRunLoopSourceContext content = {0};
            CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &content);
            CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
            CFRelease(source);
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
        };
        threadByIdentity = [[NSThread alloc] initWithBlock:createThreadBlock];
        [threadByIdentity start];
        if (threadByIdentity) {
            [sx_threadDictM setObject:threadByIdentity forKey:identify];
        }
    }
    [threadByIdentity start];

    [self performSelector:@selector(class_taskMethod:) onThread:threadByIdentity withObject:task waitUntilDone:NO];
}

三:在常驻默认线程中执行操作(线程需要随当前对象创建或销毁)

- (void)execureTask:(SXLivingThreadTask)task{
    if (!task || !self.p_thread) {
        return;
    }

    [self performSelector:@selector(threadTaskMothod:) onThread:self.p_thread withObject:task waitUntilDone:NO];
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.p_thread = [self thread];
    }
    return self;
}
- (void)dealloc{
    [self performSelector:@selector(clearThreadMethod) onThread:self.p_thread withObject:nil waitUntilDone:YES];
}
- (NSThread *)thread{
    NSThread *thread = nil;
    __weak typeof(self) wealSelf = self;
    void(^createThreadBlock)(void) = ^{
        NSRunLoop  *currentRunLoop = [NSRunLoop currentRunLoop];
        [currentRunLoop addPort:[NSPort new] forMode:NSDefaultRunLoopMode];
        while (wealSelf && wealSelf.isShouldKeepRunning) {
            [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
    };
    self.shouldKeepRunning = YES;
    thread = [[NSThread alloc]initWithBlock:createThreadBlock];
    [thread start];
    return  thread;
}
- (void)createThreadMethod:(void(^)(void))createThreadBlock{
    createThreadBlock();
}
- (void)threadTaskMothod:(void(^)(void))task{
    task ? task():nil;
}
- (void)clearThreadMethod{
    self.shouldKeepRunning = NO;
    CFRunLoopStop(CFRunLoopGetCurrent());
}