RunLoop 详解

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

概述:

RunLoop 是一个核心的 iOS 机制,它是 事件循环机制 的实现,负责管理线程的执行和调度。RunLoop 能够持续监听输入事件(如用户触摸、定时器、网络请求等)并分发给相应的处理方法,从而保持应用程序持续运行。

核心功能:

  1. 处理异步事件: RunLoop 可以管理事件源,比如定时器、触摸事件、网络响应等,确保这些事件在合适的时机被触发。
  2. 控制线程执行: 通过控制线程是否处于休眠或运行状态,RunLoop 能够让线程处于活跃状态,并等待事件的发生。
  3. 保持线程活跃: 如果没有事件需要处理,RunLoop 会让线程进入休眠状态,节省系统资源。

1. 为什么需要 RunLoop?

背景:

在多线程编程中,主线程(UI线程)必须保持活跃,才能响应用户的操作和刷新界面。没有 RunLoop,即便你创建了一个线程,也不能有效地等待和处理外部事件。

  • UI更新:当我们触发按钮点击等操作时,事件会通过 RunLoop 传递给相应的处理方法,确保 UI 在需要的时候得到更新。
  • 后台任务:在后台线程处理任务时,我们也需要 RunLoop 来监听定时器、网络请求等异步任务。

没有 RunLoop,线程就像失去了生命,即使任务没完成,它也会直接退出。

2. RunLoop 的基本工作原理

基本流程:

  1. RunLoop 启动:线程启动后,会进入 RunLoop 循环。
  2. 等待事件RunLoop 会等待外部事件的发生,比如触摸事件、定时器触发、网络回调等。
  3. 事件处理:当事件发生时,RunLoop 会将事件分发到对应的处理方法(例如响应按钮点击事件、定时器回调等)。
  4. 继续运行:当事件处理完后,RunLoop 会继续等待新的事件,或者退出。

RunLoop 状态:

  • 休眠状态:当没有事件需要处理时,RunLoop 处于休眠状态。休眠时,线程不会消耗过多的 CPU 资源。
  • 活跃状态:当有事件发生时,RunLoop 被唤醒,进入活跃状态来处理这些事件。

3. 常见用法

(1) 主线程的 RunLoop

主线程的 RunLoop 是自动开启的,常用于UI事件处理异步任务的等待

例如,在处理定时器时,你可能希望在主线程中定期执行某些操作:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateUI) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
  • 定时器会定期触发 updateUI 方法。
  • NSRunLoopCommonModes 确保定时器在滚动、拖动等事件中也能继续触发。

(2) 自定义线程的 RunLoop

对于自定义线程(非主线程),你需要手动创建并启动 RunLoop

- (void)startCustomThread {
    NSThread *customThread = [[NSThread alloc] initWithTarget:self selector:@selector(runThread) object:nil];
    [customThread start];
}

- (void)runThread {
    @autoreleasepool {
        // 创建并启动 RunLoop
        [[NSRunLoop currentRunLoop] run]; // 必须显式调用,线程才能持续运行
    }
}

[[NSRunLoop currentRunLoop] run] 启动线程的 RunLoop,使其持续运行,处理事件。

(3) 使用 RunLoop 处理定时器

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
  • 这样可以确保定时器的回调不会被滚动等事件阻塞。
  • NSRunLoopCommonModes 模式确保在用户滚动屏幕时,定时器依然可以触发。

4. 解决实际问题:

(1) 主线程阻塞问题

RunLoop 可以有效避免主线程阻塞。很多时候我们需要执行耗时操作(比如网络请求),但不能让主线程被阻塞,否则界面无法响应。

- (void)fetchData {
    NSURL *url = [NSURL URLWithString:@"https://example.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // 网络请求完成后,更新 UI
        dispatch_async(dispatch_get_main_queue(), ^{
            // 更新 UI
        });
    }];
    
    [task resume];
}
  • 通过 dispatch_async 把 UI 更新放到主线程,避免主线程阻塞。
  • 事件循环 让主线程保持活跃,直到请求完成,才处理回调。

(2) 后台任务与定时器的配合

当我们在后台线程执行定时任务时,必须确保线程运行不被中断。使用 RunLoop 能保证后台线程的活跃:

- (void)performBackgroundTask {
    [NSThread detachNewThreadSelector:@selector(executeBackgroundTask) toTarget:self withObject:nil];
}

- (void)executeBackgroundTask {
    @autoreleasepool {
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(backgroundTask) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];  // 保持线程活跃
    }
}

- (void)backgroundTask {
    NSLog(@"Background task executed");
}

通过 RunLoop 保证定时器在后台线程中正常触发,否则后台线程执行完毕后会自动退出,定时器就会停止。

5. 注意事项与优缺点

优点:

  • 节省系统资源:通过在没有事件时让线程进入休眠状态,RunLoop 可以有效减少不必要的 CPU 消耗。
  • 异步任务管理:能够很方便地在多线程中管理事件源(如定时器、网络请求等),确保线程在等待事件时不会结束。
  • 灵活的线程控制RunLoop 提供了灵活的方式来控制线程,确保线程在处理事件时能一直活跃。

缺点:

  • 不能主动退出RunLoop 只会在有事件时才会退出,如果没有事件源,线程会一直保持休眠状态,因此我们需要手动管理退出条件。
  • 性能问题:过多的事件源可能会增加线程的调度开销,影响应用的性能。
  • 内存管理RunLoop 本身并不负责对象的内存管理,所以在使用时要注意内存泄漏(例如通过定时器等引用)。

一、RunLoop 的核心知识

1. RunLoop 的五个主要阶段

  1. kCFRunLoopEntry(进入)

  2. kCFRunLoopBeforeTimers(处理定时器)

  3. kCFRunLoopBeforeSources(处理输入事件、UI 事件、手势、触摸、逻辑等)

  4. kCFRunLoopBeforeWaiting(准备睡眠,提交渲染)

  5. kCFRunLoopAfterWaiting(被唤醒)

  6. kCFRunLoopExit(退出)

2. RunLoop 的几种模式

模式名称

描述

kCFRunLoopDefaultMode

主线程 UI 默认模式(动画、UI 事件等)

UITrackingRunLoopMode

ScrollView 滑动时使用,优先处理滑动事件

kCFRunLoopCommonModes

一个集合,会自动包含 Default + Tracking

主线程 RunLoop 通常运行在 kCFRunLoopDefaultMode

滑动时临时切到 UITrackingRunLoopMode。

二、页面更新、动画、渲染原理

1. CPU / GPU 的三阶段流水线

每一帧都分为三个行为:

帧 n:CPU 处理(布局、事件、动画计算)

帧 n:提交渲染指令

帧 n:GPU 渲染上一帧内容(帧 n-1)

帧 n:显示上一帧内容(帧 n-2)

所以 GPU 和 CPU 并不共享同一帧的时间,是“阶梯式并行”。

2. kCFRunLoopBeforeSources 能否导致卡顿?

能,主要因为:

  • UI 布局(AutoLayout)

  • 文本绘制计算

  • 大量对象分配、销毁

  • JSON 解析

  • 手势响应逻辑

  • 主线程阻塞(锁等待)

虽然渲染在 GPU,但 渲染之前的所有“准备”工作都由 CPU 做。如果这一阶段 CPU 超过帧预算(16.67ms),就会卡。

三、卡顿原理(CPU/GPU 双方向)

1. CPU 卡顿

  • 如果某一帧 CPU 用了 20ms > 16.67ms

  • GPU 没法按时拿到渲染指令

  • 直接掉帧

2. GPU 卡顿

  • 如果某一帧 GPU 渲染很慢(如大量模糊、阴影、离屏渲染)

  • GPU 也无法按时完成

  • 同样掉帧

更高帧率 = 时间预算更少,CPU 和 GPU 压力显著增大。

不过 iOS 会自动降帧(ProMotion),不一定每次都跑 120Hz。

五、CPU 是否会“休息”?

场景:CPU 本帧只用 5ms

  • 剩下的 11.67ms 主线程会休眠,等待下一次 VSync 或事件唤醒。

CPU 本帧用了 20ms(大于 16ms)

  • 不会等两帧才继续

  • 处理完当帧后立即进入下一次事件循环

  • 而不是按 VSYNC 时间排队执行

VSync 的队列机制

  • 没有任务排队机制

  • VSync 只是一个“屏幕刷新信号”

  • CPU 超过帧预算 → 掉帧,而不是积压任务

六、Timer(NSTimer / CFRunLoopTimer)行为

1. kCFRunLoopBeforeTimers 阶段的主要耗时是?

定时器的回调执行时间。

2. 卡顿会导致 Timer 不准吗?会!

Timer 不是基于硬件时钟,是基于 RunLoop 事件驱动:

  • RunLoop 忙 → Timer 延迟

  • Timer 回调会比实际时间明显滞后

3. Timer 延迟后的行为(重点)

会采用:回调一次 + “延迟执行”

不会补偿,也不会自动“计算时间差”来保持精度。

例子:需要 1 秒执行一次,如果 CPU 卡顿 2 秒,第二次触发时间会直接变成 3 秒,不会补发“2 次补偿回调”。

领域

核心结论

RunLoop 阶段

BeforeSources 执行逻辑和 UI 事件,是 CPU 卡顿重灾区

渲染流程

CPU → 提交指令 → GPU 渲染上一帧

卡顿原因

CPU 重逻辑 或 GPU 重渲染

120Hz

帧预算减半,CPU/GPU 压力更高

CPU 是否休息

会休眠等待下一帧,如果耗时过长则掉帧

VSync 队列

没有任务排队机制

Timer 行为

不补偿,不自动对齐系统时间;卡顿会导致回调延迟

如何精确计时

需要自己用时间戳计算差值

iOS 卡顿的本质:主线程卡住了

当主线程 RunLoop 在某一阶段(大多是 BeforeSources)超过 一帧预算

  • 60 FPS → 16.67ms

  • 120 FPS → 8.33ms

就会出现卡顿(掉帧)。

所以卡顿监控核心就是:

盯住主线程是否连续多帧没有进入下一次 RunLoop 切换

卡顿监控RunLoop Observer

监控 RunLoop 是否卡在某个阶段太久。

📌 原理

  1. 给主线程 RunLoop 添加 CFRunLoopObserver

  2. 监听阶段(尤其是 BeforeSources、BeforeWaiting)

  3. 如果两个阶段之间超过阈值(50ms、100ms)→ 卡顿

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值