iOS:常驻线程

作者: 丶墨墨丶 | 来源:发表于2019-08-15 17:05 被阅读0次

常驻线程基本的思路都是等待信号>收到信号>执行回调>继续等待信号,在项目开发中需要将一些耗时的,不紧要的任务放到常驻子线程中处理。
记录两种实现常驻线程的方式:

一、NSThread+RunLoop

- (void)onStart:(UIButton*)sender
{
    NSLog(@"start %@",self.navigationItem.title);
    [NSThread detachNewThreadSelector:@selector(onThread:) toTarget:self withObject:nil];
    
}
 
- (void)onThread:(id)sneder
{
    NSLog(@"run ...");
    self.workerThread_NS = [NSThread currentThread];
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onCheckNSTask:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"over");
}
- (void)onCheckNSTask:(id)sender
{
    NSLog(@"checking ..");
}

或者

- (void)onStart:(UIButton*)sender
{
    NSLog(@"start %@",self.navigationItem.title);
    [NSThread detachNewThreadSelector:@selector(onThread:) toTarget:self withObject:nil];
    
}
 
- (void)onThread:(id)sneder
{
    self.workerThread_NS = [NSThread currentThread];
    // Should keep the runloop from exiting
    CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    
    BOOL runAlways = YES; // Introduced to cheat Static Analyzer
    while (runAlways) {
        
        CFRunLoopRun();
        
    }
    
    // Should never be called, but anyway
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}

二、NSThread+信号量

/**
 常驻线程
 */
@interface ResidentThread : NSObject
-(void)doAction:(dispatch_block_t)action;
-(void)cancel;
@end

@implementation ResidentThread{
    NSMutableArray *actions;
    NSThread *thread;
    dispatch_semaphore_t sem;
    bool cancel;
}
-(id)init{
    self = [super init];
    actions = [NSMutableArray array];
    // 创建信号量
    sem = dispatch_semaphore_create(0);
    // 创建一个新线程
    thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [thread start];
    return self;
}

-(void)run{
    while (true) {
        // 等待信号量,信号量减1
        dispatch_semaphore_wait(sem, -1);
        // 收到信号
        // 如果线程已经取消了,那么退出循环
        if(cancel){
            break;
        }
        // 开始执行任务
        dispatch_block_t block = [actions firstObject];
        if(block){
            [actions removeObject:block];
            block();
        }
        
    }
}

// 执行某个任务
-(void)doAction:(dispatch_block_t)action{
    if(!cancel){ // 如果线程已经cancel了,那么直接忽略
        // 将任务放入数组
        [actions addObject:[action copy]];
        // 发送信号,信号量加1
        dispatch_semaphore_signal(sem);
    }
}

// 终止常驻线程
-(void)cancel{
    cancel = YES;
    // 线程取消后,清空所有的回调
    [actions removeAllObjects];
    // 相当于发送一个终止任务的信号
    dispatch_semaphore_signal(sem);
}
@end

doAction::这个方法接收一个dispatch_block_t的参数,代表实际需要让常驻线程执行的任务。
cancel:终止该常驻线程。
为了安全起见,这里采用的是标记位的方式。另外要注意到,cancel方法里面额外发送了一个信号,这个信号的作用类似于发送了一个终止任务的信号。

相关文章

  • iOS:常驻线程

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

  • iOS 常驻线程

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

  • iOS 常驻线程

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

  • iOS RunLoop(一)

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

  • iOS RunLoop

    RunLoop 应用:NSTimer、 PerformSelector、常驻线程iOS 中有两套API访问 Fo...

  • iOS 创建常驻线程

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

  • iOS RunLoop常驻线程

    常驻线程的作用: 让一个一直存在的子线程,等待其他线程发来消息,处理其他事件。 1.设置成全局的,如果是线程对象是...

  • iOS 创建常驻线程

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

  • iOS GCD常驻线程

    - (void)viewDidLoad { [super viewDidLoad]; [self perf...

  • iOS面试问题

    一: iOS常驻线程 二: AFNetWorking 2.0与3.0的区别 三: 当开的后台线程太多, 如何进行内...

网友评论

    本文标题:iOS:常驻线程

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