Skip to content

进程与线程管理

1. 进程模型

1.1 鸿蒙进程模型概述

进程模型层次:
┌─────────────────────────────────────┐
│  Application(应用)                  │
│  ├── UIAbility(UI 界面入口)          │
│  └── ExtensionAbility(扩展组件)     │
├─────────────────────────────────────┤
│  Process(进程)                      │
│  ├── 应用进程(Application Process)   │
│  ├── 系统进程(System Process)        │
│  └── 服务进程(Service Process)       │
├─────────────────────────────────────┤
│  Thread(线程)                      │
│  ├── UI 线程(主线程)                │
│  ├── Worker 线程(工作线程)           │
│  └── System Thread(系统线程)        │
└─────────────────────────────────────┘

1.2 进程分类

类型说明优先级生命周期
前台进程有正在交互的 UIFOREGROUND(最高)直到用户退出
可见进程有可见但非交互的 UIVISIBLE直到不可见
服务进程有后台服务运行SERVICE直到服务停止
后台进程Activity 在后台(onBackground)BACKGROUND内存紧张时被杀
空进程无活跃组件EMPTY(最低)立即可被杀

1.3 与 Android 进程模型对比

维度Android鸿蒙
进程入口Activity/ServiceUIAbility/ExtensionAbility
进程隔离UID 隔离TokenID + 沙箱隔离
进程间通信BinderIPC (Port + MessageQueue)
进程优先级5 级(foreground→empty)6 级(含 process-group)
OOM KillerAdj 值排序重要性等级排序
多进程声明式(android:process)声明式(process 属性)
启动方式fork + Zygote 连接fork + Zygote Socket

2. 进程生命周期

2.1 UIAbility 进程状态转换

         ┌──────────────┐
         │   已创建      │
         │  onCreate    │
         └──────┬───────┘

         ┌──────▼───────┐       用户切出
         │   前台运行    │◄──────────┐
         │ onForeground │           │
         └──────┬───────┘           │
                │                    │
         ┌──────▼───────┐       重新切入
         │   后台暂停    │──────────►│
         │ onBackground │           │
         └──────┬───────┘           │
                │                    │
         ┌──────▼───────┐  长时间/低内存
         │    终止      │──────────►│
         │  onDestroy   │           │
         └──────────────┘           │

2.2 进程保活策略

arkts
// 鸿蒙进程保活机制
import { common } from '@kit.AbilityKit';

// 1. 提升进程优先级:启动前台服务
async function keepProcessAlive() {
  const foregroundService = {
    foregroundServiceType: 'common',
    notificationId: 1001,
    content: {
      title: '服务运行中',
      text: '后台任务执行中',
    }
  };
  await this.context.startForegroundService(foregroundService);
}

// 2. 使用 WorkScheduler 执行后台任务
import { workScheduler } from '@kit.BusinessKit';

await workScheduler.scheduleAbility({
  bundleName: 'com.example.myapp',
  abilityName: 'BackgroundWorkAbility',
  type: workScheduler.WorkType.WORK_TYPE_PERIODIC,
  interval: 3600000, // 1 小时
  periodic: true,
});

2.3 进程回收策略

回收优先级(从高到低):
1. 空进程 (EMPTY) — 可立即回收
2. 后台进程 (BACKGROUND) — 可回收
3. 服务进程 (SERVICE) — 谨慎回收,通知用户
4. 可见进程 (VISIBLE) — 仅在内存极紧张时
5. 前台进程 (FOREGROUND) — 几乎不回收

OOM 评分公式(简化):
score = base_score + process_type_penalty + cpu_time_penalty

3. 线程模型(Actor 模型)

3.1 ArkTS 线程模型

鸿蒙采用 Actor 模型作为核心并发模型:

Actor 特性:
├── 线程隔离:每个 Actor 运行在独立线程上
├── 消息传递:通过消息队列通信,无共享内存
├── 无锁设计:不需要同步原语,避免死锁
├── 轻量级:线程创建开销低(~100μs)
└── 结构化:线程池统一管理

3.2 TaskPool(推荐方案)

arkts
// TaskPool 是系统管理的线程池,适合短时任务
import { taskpool } from '@kit.ArkTaskPool';

// 定义任务函数
@worker
function fetchData(url: string): string {
  // 在工作线程中执行网络请求
  return http.get(url).sync();
}

// 使用 TaskPool
async function loadData() {
  // 1. 注册任务
  await taskpool.register(fetchData);

  // 2. 提交任务
  const promise = taskpool.run(fetchData, ['https://api.example.com/data']);

  // 3. 获取结果
  const result = await promise;
  console.log('Data: ' + result);
}

// TaskPool vs Worker 对比:
// TaskPool: 系统管理,自动调度,适合短时 (< 5s) 任务
// Worker:   手动管理,适合长时 (> 5s) 或常驻任务

3.3 Worker(长时任务)

arkts
// Worker 适合长时间运行或常驻任务
// 需要手动创建和管理

@worker
class MyWorker {
  private running: boolean = false;

  start() {
    this.running = true;
    while (this.running) {
      // 执行常驻任务
      this.processData();
    }
  }

  stop() {
    this.running = false;
  }

  private processData() {
    // 处理数据
  }
}

// 创建和销毁 Worker
const worker = new MyWorker();
worker.start();
// ... 完成时
worker.stop();

3.4 线程池使用

arkts
import { thread } from '@kit.ArkThread';

// 1. 获取系统线程池
const executor = thread.createExecutor();

// 2. 提交任务到线程池
const future = executor.submit(() => {
  // 异步任务
  return heavyComputation();
});

// 3. 获取结果
const result = future.get(); // 阻塞等待

// 4. 线程池资源释放
executor.shutdown();

3.5 主线程与工作线程

arkts
// ⚠️ 关键规则:UI 操作只能在主线程进行

@Entry
@Component
struct WorkerDemo {
  @State message: string = '加载中...';
  @State isLoading: boolean = false;

  aboutToAppear() {
    // 在主线程:可以直接更新 @State
    this.message = '开始加载';

    // 提交到工作线程
    taskpool.run(() => {
      // 工作线程:不能更新 @State
      const data = this.fetchFromServer();
      // ✅ 正确:通过 callback 回到主线程更新
      this.$emit('dataLoaded', data);
    }).catch((err: Error) => {
      // ✅ 正确:主线程中处理错误
      this.message = '加载失败: ' + err.message;
    });
  }

  fetchFromServer(): string {
    // 模拟网络请求
    return 'Server Data';
  }
}

4. 线程调度

4.1 调度策略

策略说明适用场景
SCHED_OTHERCFS 公平调度(默认)普通应用任务
SCHED_FIFO实时先入先出音视频处理
SCHED_RR实时轮转调度实时通信任务
SCHED_DEADLINE截止期调度严格实时任务

4.2 线程优先级

优先级范围:0(最低)~ 127(最高)
────────────────────────────────────
SCHED_DEADLINE: 0-99(高优先)
SCHED_FIFO/RR:  0-99(高优先)
SCHED_OTHER:    -20~19(相对 Linux  nice)
────────────────────────────────────
系统限制:用户线程最高优先级 ≤ 63(防止饿死内核)
arkts
import { thread } from '@kit.ArkThread';

// 创建高优先级线程
const highPriorityThread = await thread.startThread({
  name: 'high-priority-worker',
  prio: thread.ThreadPriority.HIGH,  // 优先级
  onExit: (code) => console.log('Done'),
});

5. OOM Killer

5.1 OOM 机制

OOM Killer 触发条件:
├── 可用内存 < 阈值(可配置)
├── 连续分配失败(kmalloc 返回 NULL)
└── 内存压力达到 OOM_SCORE 阈值

OOM 评分因素:
├── 进程重要性(前台 > 后台)
├── 进程驻留时间
├── 进程的 RSS/VSZ 大小
├── 进程是否有子进程
└── 手动设定的 oom_adj 值

5.2 内存回收流程

1. 内存分配失败
2. 触发内存回收(kswapd / khugepaged)
3. 扫描 LRU 链表,释放可回收页面
4. 如果仍不足 → OOM Killer 介入
5. 按重要性排序,杀死最低优先级进程
6. 释放内存 → 原请求分配成功

5.3 OOM 防护策略

arkts
// 1. 主动释放不需要的资源
@Entry
@Component
struct MemoryAwareComponent {
  @State imageData: string = '';

  // 页面隐藏时释放大图内存
  onWillDisappear() {
    this.imageData = ''; // 释放图片数据
  }

  // 页面显示时按需加载
  onWillAppear() {
    // 仅在需要时加载
  }
}

// 2. 使用 Weakref 管理长生命周期引用
// 3. 图片使用 decodePixel 下采样
// 4. 避免在 @State 中存放大对象
// 5. 及时关闭文件句柄和数据库连接

5.4 内存泄漏检测

检测手段:
├── DevEco Profiler Memory 面板
├── Heap Snapshot 对比
├── @State 大对象检查
├── 闭包中意外引用(闭包陷阱)
└── 监听器未注销(addEventListener)

常见泄漏场景:
├── @State 存储大数组/对象
├── 定时器未清理(clearTimeout)
├── 网络请求未 abort
├── 自定义事件监听未 removeListener
└── 闭包中持有 UIComponent 引用

6. 🎯 面试高频考点

Q1: 鸿蒙的 Actor 线程模型与 Android 线程模型有什么区别?

答要点

  • 鸿蒙 Actor 模型:线程隔离 + 消息传递,无共享内存,天然避免竞态条件
  • Android 线程模型:共享内存 + 同步原语(mutex/semaphore),需要手动处理同步
  • 鸿蒙 TaskPool 由系统管理,Android Handler/Executor 需要手动管理
  • 鸿蒙禁止跨线程操作 UI,Android 通过 Handler 回调到主线程

Q2: TaskPool 和 Worker 怎么选?

答要点

  • TaskPool:系统管理线程池,适合短时任务(< 5s),无需手动管理
  • Worker:手动创建管理,适合长时任务(> 5s),可常驻运行
  • TaskPool 有任务超时机制(默认 60s),Worker 无超时限制
  • TaskPool 自动回收线程,Worker 需要手动 shutdown
  • 大量短时任务优先用 TaskPool(减少线程创建开销)

Q3: 鸿蒙如何防止 OOM?

答要点

  • 架构层面:分层 OOM Killer,按重要性排序回收
  • 开发层面:避免 @State 存储大对象,及时释放资源
  • 图片处理:使用 decodePixel 下采样,按需加载
  • 懒加载:LazyForEach 按需加载列表
  • 缓存策略:实现 LruCache,设置大小上限
  • 监控:使用 Profiler 定期检测内存泄漏

💡 面试提示:Actor 模型是鸿蒙并发的核心,对比 Android 的 Handler 模型强调无锁、线程隔离的优势。TaskPool vs Worker 是高频对比题。