RunLoop篇-机制作用

2019-07-18  本文已影响0人  亲爱的大倩倩
入口函数

在我们程序中,默认是从主函数进行程序启动
按说在main函数里,顺着执行体代码,进行依次执行,最后main函数就会退出,我们的程序也会随之退出
main函数为何能保持不退出?
在main函数中,会调用UIApplicationMain函数,在内部会启动主线程Runloop,可以不断的接收消息,比如点击屏幕事件,滑动列表以及处理网络请求的返回等
接收消息后对事件进行处理,处理完之后,就会继续等待

int main(int argc, char * argv[]) {
    @autoreleasepool {
       //它会先去info.plist中去查找principalClassName的值
       //如果没有,会去AppDelegate中查找,所以我们平时的代码会写在AppDelegate中
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

当我们在AppDelegate中打个断点,在控制台跟踪就会看到,当进入main后,就创建了runloop

消息处理机制
  1. 在没有消息需要处理时,会休眠以避免资源占用
  2. 在有消息处理时,会立刻被唤醒

runloop循环不是单纯的for...while循环,而是发生一个用户态到内核态切换,以及内核态到用户态的一个切换

它维护的事件循环,可以用来不断的处理消息或者事件,对他们进行管理
当没有消息进行处理时,会从用户态发生到内存态的切换,由此可以用来当前线程的休眠,避免资源占用
当有消息需要处理时,会发生从内核态到用户态的切换,当前的用户线程会被唤醒
所以说,状态切换才是Runloop的关键

关于用户态和内核态
  1. 用户态:
    应用程序一般都是运行在用户态上,用户进程,包括我们开发所使用的绝大多数API,都是针对用户层面的

  2. 内核态:
    在内核态往往有些陷阱指令,中断,以及一些开机关机的操作
    并且内核态里面的一些内容,可以对用户态中的一些线程进行调度和管理,包括进程间的通信

  3. 为什么区分状态:
    之所以通过切换空间来区分出了用户态和内存态,是对计算机的资源调度,资源管理进行一个统一操作,就可以合理安排资源调度,避免异常
    试想下,如果每一个用户进程,或者说一个APP,都可以促使当前用户手机关机或者中断,就太.....

  1. 何时切换:
    当我们发生了系统调用,需要使用到操作系统以及一些底层内核相关的指令或者API时,就会发生一个状态空间的切换
Runloop作用

如果我们自己写个do while循环,会发现CPU占了40%左右,但如果不写这句话,会发现Runloop的循环CPU占0,所以说它能节约CPU资源



RunLoop应用
与线程的关系

当Main函数里启动主RunLoop后,跟踪代码会发现:

  1. 主runLoop是通过主线程来创建的
  2. 线程和runloop是通过key-value形式来一一对应的, 主线程的指针会指向主runloop
runloop声明

在当前的runloops里面,根据thread的指针,可以取出当前runloop


runloop提取
  1. 子线程的runloop默认不开启
    下面的代码,在thread中,只有加了runloop才会执行timer里的内容

  2. 当线程退出后,runloop会自动退出

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   //通过变量控制线程,线程控制RunLoop,RunLoop控制timer

    LGThread *thread = [[LGThread alloc] initWithBlock:^{
        NSLog(@"%@---%@",[NSThread currentThread],[[NSThread currentThread] name]);
        [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"hello word");            // 退出线程--结果runloop也停止了
            if (self.isStopping) {
                [NSThread exit];
            }
        }];
        [[NSRunLoop currentRunLoop] run];
    }];
    
    thread.name = @"lgcode.com";
    [thread start];
}


上一篇下一篇

猜你喜欢

热点阅读