如果你是在理解React Native / Expo这类跨平台框架里的“JS 线程、UI 线程、Native 线程”可以先抓住一个核心JS 线程负责“决定做什么”UI 线程负责“把界面画出来”Native 线程负责“执行原生能力”。但严格来说“Native 线程”不是一个固定的单独线程这是最容易混淆的地方。先看整体关系React / JS 代码 │ ▼ ┌─────────────┐ │ JS线程 │ │ │ │ 状态计算 │ │ React逻辑 │ │ 业务逻辑 │ │ 网络请求 │ └──────┬──────┘ │ JS ↔ Native 通信/调用 │ ▼ ┌─────────────────────────┐ │ Native 世界 │ │ │ │ UI线程/Main线程 │ │ │ │ │ ▼ │ │ Layout / UI / 渲染 │ │ │ │ 其他Native线程 │ │ 网络 / IO / 图片 / 音频 │ │ 数据库 / 原生模块 │ └─────────────────────────┘1. JS 线程是什么比如const [count, setCount] useState(0); function onPress() { setCount(count 1); }这些JavaScript / React 代码通常是在 JS runtime 所在的线程执行。它主要负责React 组件执行状态管理业务逻辑JS 定时器事件处理数据处理发起网络请求决定 UI 应该变成什么样例如setCount(count 1)JS 线程会参与点击 ↓ JS线程 ↓ 执行 onPress() ↓ setCount() ↓ React重新计算 ↓ 产生新的UI更新2. UI线程是什么UI线程通常也叫Main ThreadMain/UI Thread它是操作系统负责处理界面相关工作的核心线程。例如 Android / iOS 中UI线程 ↓ View ↓ Layout ↓ 绘制 ↓ 屏幕所以View TextHello/Text /View并不是说View本身就是一个 JS 对象然后直接被屏幕画出来。而是JS │ │ 描述我要什么 ▼ React Native │ ▼ Native UI │ ▼ UI线程 │ ▼ 屏幕3. Native线程是什么这里要特别注意Native ≠ Native线程。Native 指的是原生代码例如Android Java / Kotlin / C iOS Objective-C / Swift / CNative 代码可以运行在多个线程。例如Native ├── UI线程 ├── IO线程 ├── 网络线程 ├── 图片处理线程 ├── 音频线程 ├── JS相关线程 └── 其他线程所以如果有人说“Native线程负责UI”这个说法其实不够准确。更准确应该说Native UI代码通常需要在UI/Main线程执行。4. 三者最重要的关系可以把它理解成一个公司JS线程 │ “我要做什么” │ ▼ ┌────────────────┐ │ Native层 │ │ │ │ UI线程 │ │ “怎么画出来” │ │ │ │ 其他线程 │ │ “怎么执行任务” │ └────────────────┘例如button.setOnPress(() { setCount(count 1); });大概可以理解成用户点击 │ ▼ UI线程接收到触摸 │ ▼ 把事件传给JS │ ▼ JS线程执行onPress │ ▼ React计算新的UI状态 │ ▼ Native侧更新 │ ▼ UI线程执行UI更新 │ ▼ 屏幕刷新5. 为什么会出现“JS线程卡顿”假设你写function test() { for (let i 0; i 10000000000; i) { // 非常耗时 } }那么JS线程 ████████████████████████████ 一直计算JS线程被占满。这时候可能出现点击事件 ↓ JS线程忙 ↓ 事件无法及时处理 ↓ React更新延迟 ↓ 用户感觉卡顿这就是常说的JS线程阻塞6. UI线程卡顿又是什么假设 UI线程正在执行非常重的任务UI线程 ████████████████████████ Layout 绘制 Layout 绘制 复杂动画 复杂绘制如果超过一帧的时间就会掉帧。例如 60 FPS1000ms / 60 ≈ 16.67ms意味着一帧大约只有16.67ms如果UI线程这一帧花了50ms就可能出现Frame 1 Frame 2 Frame 3 ████████████████ ↑ 卡顿所以JS线程卡 ≠ UI线程一定卡反过来也一样。7. React Native 为什么特别关心这三个概念因为 RN 本质上是在JavaScript ↓ React Native Runtime ↓ Native ↓ Android / iOS UI中间进行协作。传统 RN 架构可以粗略理解为┌───────────────┐ │ JS线程 │ │ React │ │ JavaScript │ └───────┬───────┘ │ │ Bridge │ ▼ ┌───────────────┐ │ Native │ │ │ │ UI线程 │ │ Native Modules│ └───────────────┘而现代 React Native 的JSI / Fabric / TurboModules架构会减少传统 Bridge 带来的序列化和通信开销。大致变成JS Runtime │ │ JSI ▼ ┌──────────────┐ │ C / Native │ └──────┬───────┘ │ ┌──────┴───────┐ ▼ ▼ UI线程 其他线程 │ ▼ Screen这也是理解React Native 新架构的关键。8. 那 Expo 又是什么如果你最近是在学Expo / React Native可以把它放到这个模型里面Expo App │ ┌──────────┴──────────┐ │ │ JavaScript Native │ │ React代码 iOS / Android │ │ ▼ ▼ JS线程 UI线程 │ ▼ 屏幕Expo 本身并不是一个“线程”。它更像是一套React Native 原生能力 工具链 开发服务9. 最容易记住的版本你可以直接记这个概念主要干什么JS线程执行 JS、React、业务逻辑UI线程处理原生 UI、布局、绘制、用户交互Native原生代码/能力的统称不是一个固定线程Native线程泛指 Native 世界中的各种线程JSIJS ↔ Native/C 更直接的通信机制Bridge传统 RN JS ↔ Native 通信机制最关键的一句话JS 是“脑子”UI线程是“画手”Native 是“整个原生世界”。Native 不等于某一个线程。如果你下一步是在学Expo / React Native 性能优化那么继续理解JS线程 → JSI → UI线程 → GPU这一整条链会非常有用。尤其是为什么Reanimated 的动画可以在 UI 线程跑而普通setState动画容易受到 JS 线程阻塞影响。
