美文网首页
RunLoop-运行循环

RunLoop-运行循环

作者: 程序萌 | 来源:发表于2018-07-13 15:59 被阅读0次

    runLoop

    一个线程一次只能执行一个任务,执行完后线程退出。如果我们需要一个机制,让线程能随时处理事件但并不退出。

    消耗很低,睡眠循环

    循环监听事件(事件需要处理不主动发起通知,而是把自身状态变成待处理,runloop去循环监听待处理事件,发现后进行处理)

    runloop底层实现推测是do_while,死循环

    main函数里面用到runloop,保证app不退出,默认是开启的

    线程保命:一个线程任务执行完就挂掉,只有任务执行不完,才会保命,这里用runloop对线程进行保命

    和多线程结合使用
    和JaveScript中的 Event loop相似

    runloop死循环存在的目的:

    • 保证程序的不退出
    • 负责监听事件 触摸、时钟、网络事件 (这些是和硬件有关系的)
    • 如果没有事件发生,就让程序进入休眠状态

    runloop分类

    主线程的runloop (主循环)
    • 默认是开启的,是在UIApplicationMain中开启 用到懒加载
    子线程的runloop (子循环)
    • 默认是关闭的 准确的说采用懒加载创建
    • 需要[NSRunLoop currentRunLoop] run];手动开启
    • 每一子线程都可以用[NSRunLoop currentRunLoop] run]获取到,但是只有第一次获取的时候才去创建,用了懒加载
    • [NSRunLoop currentRunLoop] run]获取到runloop无法被干掉,只有杀死线程,这个线程上的runloop才会消失

    runloop模式(五种)

    • 默认模式 NSDefaultRunLoopMode

    • UI模式 UITrackingRunLoopMode

      • 优先级最高
      • 只能被触摸事件触发(如果默认模式也想触发,需要都进行添加)
    • 占位模式 NSRunLoopCommonModes

      • 不是真正的模式,只是上面2个模式的占位结合
      • 相当于上面2种模式都添加

    runloop的应用

    • 用runloop创建NSTimer
      //方式一
        NSTimer * timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerModeth) userInfo:nil repeats:YES];
        NSRunLoop * mainRunLoop = [NSRunLoop currentRunLoop];
        [mainRunLoop addTimer:timer forMode:NSDefaultRunLoopMode];
        
        //方式二,可以直接触发,因为内部自动把timer加入到了runloop中,模式是默认模式NSDefaultRunLoopMode
        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerModeth) userInfo:nil repeats:YES];
    
    • 线程之间的通讯
        NSThread * runLoopThread = [[NSThread alloc]initWithTarget:self selector:@selector(oneThread) object:nil];
        [runLoopThread start];
        [self performSelector:@selector(twoThread) onThread:runLoopThread withObject:nil waitUntilDone:YES];
     
        //给线程增加一个run loop 对这个线程进行保活
    - (void)oneThread{   
    //    这里如果waitUntilDone:NO 即不用等待callBack执行完成,直接执行下面的代码
    //    如果waitUntilDone:YES即需要等待callBack执行完成后(如果执行完,线程就会释放,选择YES程序会崩溃,需要添加runloop进行线程保活),子线程才会继续执行后面的代码
            NSRunLoop * runloop = [NSRunLoop currentRunLoop];
            [runloop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
            [runloop run];
    }
    - (void)twoThread{ 
        NSLog(@"线程通讯成功");
    }
    
    
    • GCD 内部封装runloop
      使用GCD创建定时器
      优点:
      时间准确
      可以实现子线程跑定时器时,操作UI会终止定时的问题
      可以使用子线程,解决定时器跑在主线程上卡UI问题
    @interface ViewController ()
    //dispatch_source_t 设置为成员变量,不然会立即释放
    @property(nonatomic,strong) dispatch_source_t timer;
    
    @end
    
    
        // 创建一个定时器(dispatch_source_t)
        /**
          何时开始执行第一个任务  DISPATCH_TIME_NOW(现在时间)
          1.0 * NSEC_PER_SEC 每隔多长时间执行一次
         */
        _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
        dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1.0*NSEC_PER_SEC, 0);
        // 设置回调
        dispatch_source_set_event_handler(_timer, ^{
            NSLog(@"设置回调");
        });
         // 启动定时器
        dispatch_resume(_timer);
    
    //    控制器被干掉了之后,打印还在进行,使用下面方法进行关闭
    //    dispatch_source_cancel(_timer);
    

    相关文章

      网友评论

          本文标题:RunLoop-运行循环

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