美文网首页收藏iosRunlooprunloop
iOS Runloop实践(常驻线程)

iOS Runloop实践(常驻线程)

作者: YM_1 | 来源:发表于2016-04-12 18:21 被阅读2772次

    正常的线程任务完成后,线程就为finished状态,只能销毁再创建。如果想让一个线程常驻线程,实时的响应调度,则可以利用runloop高效的分配任务。
    首先创建一个线程,代码很简单

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //创建一个线程
        self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByNormal) object:nil] ;
    //
    //    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFObserver) object:nil] ;
    //
    //    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFTimer) object:nil] ;
    //
    //    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFSource) object:nil] ;
    
    
        [self.thread start];
    }
    
    
    /**
     *  一般创建runloop的方法。结果:成功
     */
    - (void)createRunloopByNormal{
        @autoreleasepool {
    
            //添加port源,保证runloop正常轮询,不会创建后直接退出。
            [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
            
            //开启runloop
            [[NSRunLoop currentRunLoop] run];
        }
    }
    

    上面的创建方式是工作中常用的方式,著名的AFNetworking就是用的这种方式开启的AFNetworking线程常驻。

    下面测试一下线程是否退出

    - (IBAction)btnClick:(id)sender {
        
        NSLog(@"-----btnClick--------");
        [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
        
    }
    
    
    - (void)test{
        NSLog(@"----->Test");
    }
    
    

    能打印出 ----->Test 说明线程没有失效。
    另外一种通过CoreFoundation创建runloop的方式

    /**
     *  通过向CFRunLoop 添加 Observer的方式,创建runloop。结果:失败
     */
    - (void)createRunloopByCFObserver{
        @autoreleasepool {
            CFRunLoopRef runloop = CFRunLoopGetCurrent();
            CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
                
                NSLog(@"CFRunLoopActivity -->%zd",activity);
                
            });
            
            CFRunLoopAddObserver(runloop, observer, kCFRunLoopDefaultMode);
            CFRelease(observer);
            
            CFRunLoopRun();
        }
    }
    
    /**
     *  通过向CFRunLoop 添加 Timer的方式,创建runloop。结果:成功
     */
    - (void)createRunloopByCFTimer{
        @autoreleasepool {
            CFRunLoopRef runloop = CFRunLoopGetCurrent();
            CFRunLoopTimerRef timer = CFRunLoopTimerCreateWithHandler(CFAllocatorGetDefault(), CFAbsoluteTimeGetCurrent(), kCFAbsoluteTimeIntervalSince1904, 0, 0, ^(CFRunLoopTimerRef timer) {
                
            });
            CFRunLoopAddTimer(runloop, timer, kCFRunLoopDefaultMode);
            
            CFRelease(timer);
            
            CFRunLoopRun();
        }
    }
    
    /**
     *  通过向CFRunLoop 添加 Source的方式,创建runloop。结果:成功
     */
    - (void)createRunloopByCFSource{
        @autoreleasepool {
            CFRunLoopRef runloop = CFRunLoopGetCurrent();
            CFRunLoopSourceContext source_context;
            bzero(&source_context, sizeof(source_context));
            CFRunLoopSourceRef source = CFRunLoopSourceCreate(CFAllocatorGetDefault(), 0,&source_context );
            
            CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode);
            CFRelease(source);
            
            CFRunLoopRun();
        }
    }
    

    通过测试,如果只是单纯的添加Observer,然后去启动runloop,runloop并不能长期的运行,会直接退出轮询。而另外的Source、Timer则能保证runloop正常运行。

    小技巧:

    1.Source、Timer、Observer可以组合使用
    2. Observer能观察到runloop运行时的各种状态,能做很多事情
    3. Timer创建会一直执行,需要在回调中将time失效。
    

    相关文章

      网友评论

        本文标题:iOS Runloop实践(常驻线程)

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