iOS 线程保活

iOS 线程保活的三种方案。
目前从网上找到三种线程保活的方案,前两种通过 RunLoop实现,第三种通过条件锁实现。
首先我们自己创建 KYThread 继承 NSThread 并重写 dealloc 方法,用于判断线程是否被销毁。

@interface KYThread : NSThread
@end
@implementation KYThread
- (void) dealloc {
    NSLog(@"线程已销毁");
}
@end

1、定时器保活子线程

原理就是将定时器作为输入源添加到运行循环中,代码如下:

@interface ViewController ()
/** 用于判断销毁线程 */
@property (nonatomic, assign) BOOL stopping;
/** 保存线程 */
@property (nonatomic, strong) KYThread *myThread;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self test_1];
}
/** 定时器保活子线程 */
- (void)test_1  {
    self.stopping = NO;
    KYThread* thread = [[KYThread alloc] initWithBlock:^{
        // 此处创建定时器是为了保活线程
        [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"子线程定时器任务");
            if (self.stopping) {
                [NSThread exit];
            }
        }];
        [[NSRunLoop currentRunLoop] run];
        /* 另一种使用timer 启动 RunLoop 的写法
        NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"子线程定时器任务");
            if (self.stopping) {
                [NSThread exit];
            }
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        [[NSRunLoop currentRunLoop] run];
         */
    }];
    [thread start];
    self.myThread = thread;
}
/** 子线程任务 */
- (void)subThreadTask {
    for (int i=0; i<10; i++) {
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"%@ ----子线程任务 %ld", [NSThread currentThread], (long)i);
    }
}
/** 触摸时,给常驻线程添加任务 */
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self performSelector:@selector(subThreadTask) onThread:self.myThread withObject:nil waitUntilDone:NO];
}

@end

2、使用端口(addPort:forMode:)保活子线程

将端口作为输入源添加到运行循环的指定模式。其实就是往RunLoop的 Mode 中添加一个source1任务。

- (void)test_2 {
    KYThread *subThread = [[KYThread alloc] initWithTarget:self selector:@selector(startRunloop) object:nil];
    [subThread setName:@"com.kpp.mythread"];
    [subThread start];
    self.myThread = subThread;
}
/* 启动子线程 RunLoop */
- (void)startRunloop {
    @autoreleasepool {
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        //如果注释了下面这一行,子线程中的任务并不能正常执行
        [runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
        NSLog(@"子线程RunLoop启动前 ===> %@", [NSThread currentThread]);
        [runLoop run];
    }
}
/** 子线程任务 */
- (void)subThreadTask {
    for (int i=0; i<10; i++) {
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"%@ ----子线程任务 %ld", [NSThread currentThread], (long)i);
    }
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//    self.stopping = YES;
    [self performSelector:@selector(subThreadTask) onThread:self.myThread withObject:nil waitUntilDone:NO];
}

3、条件锁(NSCondition)保活子线程

条件锁是让线程处于闲等状态,当有任务时唤醒线程执行任务。

@interface ViewController ()
/** 是否退出线程 */
@property(nonatomic, assign) BOOL isExitThread;
/** 保存线程将要执行的任务 */
@property(nonatomic, copy) void(^myTask)(void);
/** 条件锁 */
@property(nonatomic, strong) NSCondition *condition;
@end

@implementation ViewController
/** 条件锁保活子线程 */
- (void)test_3 {
    self.conditon = [[NSCondition alloc] init];
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(conditionThread) object:nil];
    thread.name = @"com.kpp.conditionThread";
    [thread start];
}
/** 让子线程任务进入闲等状态 */
- (void)conditionThread {
    @autoreleasepool {
        do {
            [self.conditon lock];
            if (self.myTask) {
                self.myTask();
                self.myTask = nil;
            }
            [self.conditon wait];
            [self.conditon unlock];
        } while (!self.isExitThread);
    };
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    self.myTask = ^{
        NSLog(@"条件锁常驻线程 %@", NSThread.currentThread);
    };
    [self.conditon signal];
}
@end

你可能感兴趣的:(iOS)