iOS 创建常驻线程

作者: 包砸豆沙馅 | 来源:发表于2021-04-01 19:57 被阅读0次

iOS中默认就有个主线程即mainThread,我们的UI线程指的就是主线程,一般都是在主线程中操作UI,从某个角度来讲,我们的主线程就是一个常驻线程。

一般情况下,我们开启一个子线程,让子线程去跑一个任务,当任务执行完毕之后,该线程就会被系统自动销毁。假如说 在一个遍历循环中,要执行10000次创建子线程去执行一个耗时任务,那么这么频繁的去创建和销毁线程就会造成资源的浪费,那我们为什么不让频繁使用的子线程常驻在内存中,想用的时候就用,不想用的时候让他休眠呢?

接下来就示例创建一个常驻线程。

  • 首先创建一个ThreadManager类,为类添加一个暴露类属性,一个隐私类属性:
@interface ThreadManager : NSObject
@property (nonatomic, assign, class) BOOL isShouldKeepRunning;
@end
@interface ThreadManager()
@property (nonatomic, strong, class) NSThread * residentThread;
@end

其中isShouldKeepRuning属性可以用来控制当前子线程中runloop是否停止
residentThread为要创建引用的常驻线程

  • 接下来 声明一个静态变量,开辟空间
static BOOL _isShouldKeepRuning;
static NSThread * _residentThread;

为其提供getter和setter方法

+ (BOOL)isShouldKeepRunning {
    return _isShouldKeepRuning;
}

+ (void)setIsShouldKeepRunning:(BOOL)isShouldKeepRunning {
    _isShouldKeepRuning = isShouldKeepRunning;
}

+ (NSThread *)residentThread {
    if (_residentThread == nil) {
        // thread方法为创建线程的方法,下面会写到。
        _residentThread = [self thread];
    }
    return _residentThread;
}

+ (void)setResidentThread:(NSThread *)residentThread {
    _residentThread = residentThread;
}

提供线程创建的方法 以及在子线程中获取runloop

+ (NSThread *)thread {
    NSThread * thread = nil;
    __weak typeof(self)weakSelf = self;
    void(^creatThreadBlock)(void) = ^{
        NSRunLoop * currentLoop = [NSRunLoop currentRunLoop];
        [currentLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
        while (weakSelf && weakSelf.isShouldKeepRunning) {
            [currentLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        NSLog(@"runloop 停止! ! !");
    };
    self.isShouldKeepRunning = YES;
    if (@available(iOS 10.0, *)) {
        thread = [[NSThread alloc] initWithTarget:self selector:@selector(creatThreadMethod:) object:creatThreadBlock];
    } else {
        thread = [[NSThread alloc] initWithBlock:creatThreadBlock];
    }
    thread.name = @"thread_resident";
    [thread start];
    return thread;
}

+ (void)creatThreadMethod:(void(^)(void))task {
    if (task) {
        task();
    }
}

+ (void)executeTask:(void(^)(void))task {
    [self performSelector:@selector(threadTaskMethod:) onThread:self.residentThread withObject:task waitUntilDone:NO];
}

+ (void)threadTaskMethod:(void(^)(void))task {
    if (task) {
        NSLog(@"currentThread: %@", [NSThread currentThread]);
        task();
    }
}

其中

NSRunLoop * currentLoop = [NSRunLoop currentRunLoop];
[currentLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
  • RunLoop只能获取,不能创建。 在子线程中,获取runloop,如果没有, 系统会为我们创建,如果currentLoop中没有 source0事件、source1事件、定时器、obsever 这些事件资源,那么RunLoop不会循环,会直接结束,所以要给RunLoop加一个监听端口,用来监听系统事件的发生,那么这样子才能够保证RunLoop一直循环不退出。
  • 最后将+ (void)executeTask:(void(^)(void))task; 方法暴露出来,外部就可以直接拿来使用。下面是我测试的代码和测试结果
 [ThreadManager executeTask:^{
        NSLog(@"1 1 1 子线程 执行操作 ");
    }];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [ThreadManager executeTask:^{
            NSLog(@"2 2 2 子线程 执行操作 ");
        }];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [ThreadManager executeTask:^{
            NSLog(@"3 3 3 子线程 执行操作 ");
        }];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        ThreadManager.isShouldKeepRunning = NO;
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(8.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [ThreadManager executeTask:^{
            NSLog(@"4 4 4 子线程 执行操作 ");
        }];
    });

结果如下:


常驻线程执行
  • 可见任务的执行都在同一个子线程当中,当改变isShouldKeepRunning的值,在下一次RunLoop循环的时候,RunLoop循环被打破,退出RunLoop,此时常驻线程也不复存在。
  • 后续也可以再扩展一个方法用来重新掉起一条新的常驻线程,那么可以达到在某些情况下,已经执行了很多任务,用不到这个线程,不想让这个线程在内存中存在,手动给销毁掉,在用到的时候 重新创建。

相关文章

  • iOS 创建常驻线程

    最近看了一些关于常驻线程的文章,发现了一些问题,写此文章记录一下,如果有写的不对的地方,欢迎大神指出... 常驻线...

  • iOS 创建常驻线程

    iOS中默认就有个主线程即mainThread,我们的UI线程指的就是主线程,一般都是在主线程中操作UI,从某个角...

  • iOS 常驻线程如何创建

    @interface ViewController () @property (nonatomic,strong)...

  • 转的gcd学习

    iOS开发中,多线程应用方式一般有如下几种 1 比较高层的,封装好的API:NSThread。用来创建非常驻线程以...

  • 线程常驻内存

    iOS开发中,新创建的线程,执行完成后会销毁,如何让线程常驻内存 使用场景 随时监听某些状态改变,如监听网络状态

  • iOS:常驻线程

    常驻线程基本的思路都是等待信号>收到信号>执行回调>继续等待信号,在项目开发中需要将一些耗时的,不紧要的任务放到常...

  • iOS 常驻线程

    1.创建子线程并开启线程2.给当前runloop添加port并运行runloop3.将新任务添加到已休眠的线程

  • iOS 常驻线程

    开启线程需要占用一定的内存空间(默认的情况下,主线程占1M,子线程占用512KB)且每次开辟子线程都会消耗CPU。...

  • RunLoop开辟常驻线程

    runLoop创建一个常驻线程,多次用到子线程去处理事件,避免频繁的创建,销毁线程,每条线程都有一个RunLoop...

  • iOS RunLoop(一)

    级别: ★★☆☆☆标签:「iOS」「RunLoop」「线程常驻」作者: 陈彬审校: QiShare团队 前言:这篇...

网友评论

    本文标题:iOS 创建常驻线程

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