zoukankan      html  css  js  c++  java
  • 对 runloop 的理解

    为什么需要runloop

    一般来说线程是做完事情,就生命结束了,给它续命的办法就是让它 sleep,runloop 也是这样干的

    runloop能处理的事情分为4种:

    1. source0:自定义事件源
    2. source1:基于port的事件源
    3. timer:定时器
    4. block:GCD 分配的任务

    解释下 source0 的使用:

    • 创建一个source0实例,source0持有一个perform函数
    • 把source0加入到工作线程的runloop中
    • 某对象持有source0
    • 当某些事件发生时,对象将source0状态设置为待处理,唤醒或者不唤醒工作线程都可以
    • 工作线程被唤醒之后,处理source0,也就是执行source0的perform函数

    这样一系列的操作后,就可以不定时地在指定的线程中做一些事情了。

    source1 与 source0 类似,不过它触发的时机是由系统的端口触发的。

    那为什么需要搞这么复杂,无非就是想在指定的线程做事情嘛?

    以下是我的猜测:

    让指定线程执行某段代码,分为两种情况:

    (1)指定的线程工作已经做完了,那它就已经结束生命了,没有办法执行了,为了解决这个问题,runloop就要在没有事情做时休眠

    (2)指定的线程工作还没有完成,那我们就可以在这个线程的任务后面添加任务了吗?

    不行的,因为没有经过特殊处理的线程是在执行代码,而不是任务,任务是GCD中的概念。

    比如:我创建一个线程,并让这个线程执行以下方法:

    [NSThread detachNewThreadSelector:@selector(doit) toTarget:self withObject:nil];
    func doit() {
           let x = 0  
    }

    当doit方法 return 了,线程的事情也就做完了,是没有办法动态添加任务的。

    所以iOS选择的解决办法是在runloop中提前埋一个口子

    当然 GCD 的 block任务就是另一种方式啦

    source0 与 source1 的区别

    它们针对的场景是不一样,source0 是给同一个进程内的其他线程调用的,这种调用是不需要经过操作系统的,source1 是给其他进程调用的,这种调用必须通过操作系统,所以就只能通过端口了。

    selector是使用source0和timer实现的

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self performSelectorOnMainThread:@selector(asdf) withObject:nil waitUntilDone:NO];
        });

    在方法 asdf 中打断点,结果如下:

    [self performSelector:@selector(asdf) withObject:nil afterDelay:1];

    一个很重要的Demo

    - (void)inSubThread {
        [self performSelector:@selector(asdf) withObject:nil afterDelay:1];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        NSLog(@"自定义代码");
    }
    
    - (void)asdf {
        NSLog(@"asdf");
    }

    是“自定义代码”先打印,还是“asdf”先打印?

    答案: asdf 先打印

    只有runloop退出了流程才能接着走,“自定义代码”才能被打印出来

    因为runloop不退出的话,run 方法也就无法 return,不 return 也就没办法接着执行下一行代码

    NSLog(@"自定义代码"); 只是一句代码,它不是任务

  • 相关阅读:
    vue+element ui 表格自定义样式溢出隐藏
    vue自定义指令directives使用及生命周期
    前端如何下载文件
    js实现活动倒计时
    echarts自定义提示框数据
    vue项目如何刷新当前页面
    数据库——关于索引
    Javascript节点选择
    asp.net 身份验证(Update)
    ASP.config配置
  • 原文地址:https://www.cnblogs.com/tangjuanj/p/13162939.html
Copyright © 2011-2022 走看看