ArkTS 进程与线程相关
异步
异步指程序在执行某些操作时不必要等待其完成,而可以执行其他的操作。当异步操作完成时,程序会得到通知并处理结果。异步与同步是相对的。总的来说,异步操作是通过并发的方式来提高程序的性能,但也需要注意异步的调用顺序和时机。
ArkTS 支持标准的 JavaScirpt
异步语法 async/await
,并引入了 Promise
作为异步操作的基础。也就是说,下文这一块都和 JavaScript
异步操作相近。
Promise
Promise
是一种用于处理异步操作的对象。Promise
对象有三种状态:pending
、fulfilled
和 rejected
。Promise
对象的状态一旦变为 fulfilled
或 rejected
,就会调用相应的回调函数:resolve
和 reject
。
const promise: Promise<number> = new Promise((resolve, reject) => {
setTimeout(() => {
const value = Math.random();
if (value > 0.5) {
resolve(value);
} else {
reject(value);
}
}, 1000);
});
promise.then((value: number) => {
console.log(`Fulfilled: ${value}`);
}).catch((value: number) => {
console.log(`Rejected: ${value}`);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
之后,在调用这个 Promise
对象时,可以使用 then
方法重写 resolve
回调函数、catch
方法重写 reject
回调函数。也就是说,catch
和 then
方法一定在 Promise
对象的函数体执行后进行。
async/await
将 async/await
和 Promise
配合可以实现同步风格的异步编程,相当于一种语法糖。我们可以在函数前面加上 ansyc
将其变为异步函数。假设这一函数原来返回 string
类型,现在就应当返回 Promise<string>
类型。一般的操作是在该函数中创建一个 Promise
对象或者调用另一个异步函数,然后返回 Promise
对象。
async function asyncFunction(): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello, World!');
}, 1000);
});
}
2
3
4
5
6
7
在调用这个异步函数时,可以使用 await
关键字等待异步函数的返回值。await
关键字只能在异步函数中使用,否则会报错。
async function main() {
const value: string = await asyncFunction();
console.log(value);
}
2
3
4
我们可以看出,使用了 await
后,函数返回值又变成了 string
类型,相当于进行了解包。这样,我们就可以利用 async/await
,类似同步地进行异步操作。
并发模型
并发模型是用来实现不同应用场景中并发任务的编程模型,常⻅的并发模型分为基于内存共享的并发模型和基于消息通信的并发模型。
- 基于内存共享的并发模型:多个线程共享同一块内存,通过进程锁来保证数据的一致性。
- 基于消息通信的并发模型:多个线程之间通过消息传递机制来进行通信,不共享内存。
- Actor 模型:将并发任务封装为一个个独立的 Actor(角色),角色独占内存,通过序列化通信将结果不断发送给其他角色消费(在 ArkTS 中,一般为
UI
线程)。 - TaskPool 机制:在主线程封装任务抛给任务队列,系统选择合适的工作线程,进行任务的分发及执行,再将结果返回给主线程。
- Worker 机制:为应用程序提供多线程的运行环境,实现宿主线程分离,避免类似于计算密集型或高延迟的任务阻塞宿主线程的运行。每个 Worker 启动存在一定的内存开销,需要限制 Worker 的子线程数量。
- Actor 模型:将并发任务封装为一个个独立的 Actor(角色),角色独占内存,通过序列化通信将结果不断发送给其他角色消费(在 ArkTS 中,一般为
一般来说,大量或者调度点较分散的任务适合使用 TaskPool
机制,而计算密集型、长时间运行、有关联的同步任务适合使用 Worker
机制。
可以参阅 多线程并发 和 CPU 密集型任务开发指导 来查看更多示例。
Stage 模型的应用间跳转
应用间跳转对于手机应用来说十分常见(比如,万恶的摇一摇开屏广告),它指从一个应用跳转到另一个应用、传递相应的数据并执行功能。在 ArkTS 中,通常有两种应用间跳转的方式:
- 拉起指定应用:明确指定跳转的目标应用,实现应用跳转。从
API 12
开始,应当使用应用链接来拉起目标应用页面。 - 拉起指定类型的应用:通过指定应用类型,拉起垂类应用面板。
应用链接
应用链接是指可以将用户引导至特定应用内特定位置或相关网⻚(如果未安装目标应用)的 URL
。它的运作机制如下:
推荐使用
App Linking
实现,这样可以提高安全性并实现未安装自动跳转网页。
Stage 模型的进程和线程
进程
系统中进程包括:
- 主进程:应用中(同一
Bundle
名称)的所有UIAbility
、ServiceExtensionAbility
和DataShareExtensionAbility
均是运行在同一个进程中,如下图中绿色部分的 “Main Process
”。 - 辅助进程:应用中的所有同一类型
ExtensionAbility
均是各自运行在一个独立进程中,如下图中蓝色部分的 “FormExtensionAbility Process
”、“InputMethodExtensionAbility Process
”、其他ExtensionAbility Process
。 - WebView:
WebView
拥有独立的渲染进程,如下图中⻩色部分的 “Render Process
”。
进程模型
系统应用还可以申请多进程权限,相当于有多个上述的进程模型。
线程
线程是进程中的执行单元,一个进程可以包含多个线程。线程之间共享进程的资源,但可以执行不同的任务。在 ArkTS 中,线程主要有以下几种:
- 主线程:负责
UI
绘制、管理主线程和其他线程的 ArkTS 引擎实例、分发交互事件等。 - 工作线程:如前文介绍的
TaskPool
和Worker
线程。