From b290a276eb0c41d0f55415911bbd9b32e13adbbe Mon Sep 17 00:00:00 2001 From: yp9522 Date: Thu, 29 May 2025 18:22:45 +0800 Subject: [PATCH] arkts-utils .md modify Signed-off-by: yp9522 --- .../arkts-async-lock-introduction.md | 8 +- .../arkts-collections-introduction.md | 130 +++++++++--------- .../arkts-condition-variable-introduction.md | 6 +- .../arkts-utils/arkts-sendable-module.md | 18 +-- .../arkts-utils/arkts-sendable.md | 84 +++++------ .../arkts-utils/arraybuffer-object.md | 18 +-- .../arkts-utils/ason-parsing-generation.md | 8 +- .../arkts-utils/async-concurrency-overview.md | 30 ++-- .../batch-database-operations-guide.md | 22 +-- .../arkts-utils/concurrency-overview.md | 12 +- .../concurrent-loading-modules-guide.md | 18 +-- .../cpu-intensive-task-development.md | 28 ++-- .../arkts-utils/global-configuration-guide.md | 26 ++-- .../independent-time-consuming-task.md | 12 +- .../interthread-communication-overview.md | 14 +- .../io-intensive-task-development.md | 14 +- .../arkts-utils/long-time-task-guide.md | 10 +- .../arkts-utils/long-time-task-overview.md | 6 +- .../arkts-utils/makeobserved-sendable.md | 10 +- .../arkts-utils/multi-thread-cancel-task.md | 12 +- .../multi-thread-concurrency-overview.md | 16 +-- .../arkts-utils/multi-time-consuming-tasks.md | 10 +- .../multithread-develop-overview.md | 10 +- .../arkts-utils/native-interthread-shared.md | 20 +-- .../arkts-utils/normal-object.md | 4 +- .../arkts-utils/resident-task-guide.md | 14 +- .../arkts-utils/resident-task-overview.md | 6 +- .../arkts-utils/sendable-constraints.md | 34 ++--- .../arkts-utils/sendable-freeze.md | 10 +- .../arkts-utils/sendable-guide.md | 6 +- .../sendablelrucache-recent-list.md | 10 +- .../arkts-utils/shared-arraybuffer-object.md | 6 +- .../arkts-utils/sync-task-development.md | 27 ++-- .../arkts-utils/taskpool-async-task-guide.md | 8 +- .../taskpool-communicates-with-mainthread.md | 14 +- .../arkts-utils/taskpool-introduction.md | 44 +++--- .../arkts-utils/taskpool-vs-worker.md | 22 +-- .../arkts-utils/taskpool-waterflow.md | 16 +-- .../time-consuming-task-overview.md | 14 +- .../arkts-utils/transferabled-object.md | 12 +- .../worker-communicates-with-mainthread.md | 6 +- .../arkts-utils/worker-introduction.md | 70 +++++----- .../worker-invoke-mainthread-interface.md | 8 +- .../worker-postMessage-sendable.md | 18 +-- 44 files changed, 447 insertions(+), 444 deletions(-) diff --git a/zh-cn/application-dev/arkts-utils/arkts-async-lock-introduction.md b/zh-cn/application-dev/arkts-utils/arkts-async-lock-introduction.md index d877c573027..91cb9db202f 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-async-lock-introduction.md +++ b/zh-cn/application-dev/arkts-utils/arkts-async-lock-introduction.md @@ -1,10 +1,10 @@ # 异步锁 -为了解决多线程并发实例间的数据竞争问题,ArkTS引入了异步锁能力。异步锁可能会被类对象持有,因此为了更方便地在并发实例间获取同一个异步锁对象,[AsyncLock对象](../reference/apis-arkts/js-apis-arkts-utils.md#asynclock)支持跨线程引用传递。 +为了解决多线程并发实例间的数据竞争问题,ArkTS引入了异步锁能力。异步锁可以被类对象持有,因此[AsyncLock对象](../reference/apis-arkts/js-apis-arkts-utils.md#asynclock)支持跨线程引用传递,以便在并发实例间更方便地获取同一个异步锁对象。 -由于ArkTS语言支持异步操作,阻塞锁容易产生死锁问题,因此在ArkTS中仅支持异步锁(非阻塞式锁)。同时,异步锁还可以用于保证单线程内的异步任务时序一致性,防止异步任务时序不确定导致的同步问题。 +ArkTS支持异步操作,因此仅使用异步锁,避免死锁问题。异步锁还能确保单线程内异步任务的时序一致性,防止同步问题。 -更多异步锁相关接口,请参见[异步锁ArkTSUtils.locks](../reference/apis-arkts/js-apis-arkts-utils.md#arktsutilslocks)。 +更多异步锁相关接口,请参见[异步锁 ArkTSUtils.locks](../reference/apis-arkts/js-apis-arkts-utils.md#arktsutilslocks)。 > **说明:** > @@ -12,7 +12,7 @@ ## 使用示例 -为了防止[@Sendable共享对象](arkts-sendable.md)在不同线程修改共享变量导致的竞争问题,可以使用异步锁保护数据。示例如下: +为了防止[@Sendable共享对象](arkts-sendable.md)在不同线程中修改共享变量导致的竞争问题,可以使用异步锁来保护数据。示例如下: ```ts import { ArkTSUtils, taskpool } from '@kit.ArkTS'; diff --git a/zh-cn/application-dev/arkts-utils/arkts-collections-introduction.md b/zh-cn/application-dev/arkts-utils/arkts-collections-introduction.md index 8d315a98f3a..9a1f3b84ded 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-collections-introduction.md +++ b/zh-cn/application-dev/arkts-utils/arkts-collections-introduction.md @@ -4,13 +4,13 @@ ArkTS共享容器([@arkts.collections (ArkTS容器集)](../reference/apis-arkts/js-apis-arkts-collections.md))是一种在并发实例间共享传输的容器类,可以用于并发场景下的高性能数据传递。功能与Ecmascript262规范定义的容器类似,但仍然有部分差异,具体可见[共享容器与原生API方法的行为差异对比](#共享容器与原生api方法的行为差异对比)。 -ArkTS共享容器在多个并发实例间传递时,默认采用引用传递,允许多个并发实例操作同一个容器实例。此外,还支持拷贝传递,即每个并发实例拥有一个独立的ArkTS容器实例。 +ArkTS共享容器默认采用引用传递,允许多个并发实例操作同一个容器实例。还支持拷贝传递,每个并发实例拥有一个独立的容器实例。 -ArkTS共享容器不是线程安全的,内部使用了fail-fast(快速失败)机制,即当检测到多个并发实例同时对容器进行结构性修改时,会触发异常。因此,在多线程场景下修改容器内属性时,开发者需要使用ArkTS提供的[异步锁](arkts-async-lock-introduction.md)机制保证ArkTS容器的安全访问。 +ArkTS共享容器不是线程安全的,内部使用了fail-fast(快速失败)机制,即当检测到多个线程同时对容器进行结构性修改时,会触发异常。因此,在多线程场景下修改容器内属性时,开发者需要使用ArkTS提供的[异步锁](arkts-async-lock-introduction.md)机制保证ArkTS容器的安全访问。 -ArkTS共享容器包含如下几种:[Array](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsarray)、[Map](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsmap)、[Set](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsset)、[TypedArray](../reference/apis-arkts/js-apis-arkts-collections.md#collectionstypedarray)(Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、Uint32Array、Uint8ClampedArray、Float32Array)、[ArrayBuffer](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsarraybuffer)等,具体可见[@arkts.collections (ArkTS容器集)](../reference/apis-arkts/js-apis-arkts-collections.md)。 +ArkTS共享容器包括Array、Map、Set、TypedArray(Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、Uint32Array、Uint8ClampedArray、Float32Array)、ArrayBuffer等。具体可见[@arkts.collections (ArkTS容器集)](../reference/apis-arkts/js-apis-arkts-collections.md)。 -容器集使用示例如下: +ArkTS容器集使用示例如下: ```ts import { ArkTSUtils, collections, taskpool } from '@kit.ArkTS'; @@ -60,44 +60,44 @@ struct Index { ## 共享容器与原生API方法的行为差异对比 -ArkTS提供了Sendable数据相关的共享容器集,接口行为与原生API存在部分差异,具体可见下文对比。 +ArkTS提供了Sendable数据相关的共享容器集。接口行为与原生API存在部分差异,具体可见下文对比。 > **说明:** > -> ArkTS共享容器的类型与Ecmascript262规范定义的原生容器的类型不同,因此使用原生容器Array的isArray()方法判断collections.Array实例对象会返回false。 +> ArkTS共享容器的类型与Ecmascript262规范定义的原生容器的类型不同,因此使用原生容器的isArray()方法判断collections.Array实例对象会返回false。 > -> ArkTS共享容器跨线程传递采用引用传递方式,与原生容器相比效率更高,如果开发者需要跨线程传输的数据量很大,建议使用ArkTS共享容器。 +ArkTS共享容器采用引用传递方式,与原生容器相比效率更高。若需跨线程传输大量数据,建议使用ArkTS共享容器。 ### Array -支持原生容器Array通过[collections.Array.from](../reference/apis-arkts/js-apis-arkts-collections.md#from)方法转换为ArkTS Array容器;支持通过原生容器Array的from方法将ArkTS Array容器转换为原生容器Array。 +支持原生容器Array通过[collections.Array.from](../reference/apis-arkts/js-apis-arkts-collections.md#from)方法转换为ArkTS Array容器。支持通过原生容器Array的from方法将ArkTS Array容器转换为原生容器Array。 | 原生API方法 | ArkTS容器集方法 | 是否有行为差异 | 在ArkTS容器中的差异表现 | | -------- | -------- | -------- | -------- | | length: number | readonly length: number | 是 | 为了防止undefined扩散,不允许设置length。 | -| new(arrayLength ?: number): any[] | static create(arrayLength: number, initialValue: T): Array | 是 | 为了防止undefined扩散,构造函数中必须提供一个初始值。 | +| new(arrayLength ?: number): any[] | static create(arrayLength: number, initialValue: T): Array | 是 | 为了防止undefined扩散,构造函数中必须提供一个初始值。| | new <T>(arrayLength: number): T[] | constructor() | 否 | / | -| new <T>(...items: T[]): T[] | constructor(first: T, ...left: T[]) | 是 | 为了防止undefined扩散,构造函数中必须提供一个初始值,继承场景下,无法调用该函数进行对象构造。 | +| new <T>(...items: T[]): T[] | constructor(first: T, ...left: T[]) | 是 | 为了防止undefined扩散,构造函数中必须提供一个初始值,继承场景下,无法调用该函数进行对象构造。| | from<T>(arrayLike: ArrayLike<T>): T[] | static from<T>(arrayLike: ArrayLike<T>): Array<T> | 否 | / | | from<T, U>(iterable: Iterable<T> \| ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[] | static from<U, T>(arrayLike: ArrayLike<U> \| Iterable<U>, mapFn: ArrayFromMapFn<U, T>): Array<T> | 否 | / | -| pop(): T \| undefined | pop(): T \| undefined | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| push(...items: T[]): number | push(...items: T[]): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| concat(...items: ConcatArray<T>[]): T[] | concat(...items: ConcatArray<T>[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| concat(...items: (T \| ConcatArray<T>)[]): T[] | concat(...items: ConcatArray<T>[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| join(separator?: string): string | join(separator?: string): string | 否 | / | -| shift(): T \| undefined | shift(): T \| undefined | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| pop(): T \| undefined | pop(): T \| undefined | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| push(...items: T[]): number | push(...items: T[]): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| concat(...items: ConcatArray<T>[]): T[] | concat(...items: ConcatArray<T>[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| concat(...items: (T \| ConcatArray<T>)[]): T[] | concat(...items: ConcatArray<T>[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| join(separator?: string): string | 否 | / | +| shift(): T \| undefined | shift(): T \| undefined | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| | slice(start?: number, end?: number): T[] | slice(start?: number, end?: number): Array<T> | 否 | / | -| sort(compareFn?: (a: T, b: T) => number): this | sort(compareFn?: (a: T, b: T) => number): Array<T> | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。 | -| unshift(...items: T[]): number | unshift(...items: T[]): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| sort(compareFn?: (a: T, b: T) => number): this | sort(compareFn?: (a: T, b: T) => number): Array<T> | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。| +| unshift(...items: T[]): number | unshift(...items: T[]): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| | indexOf(searchElement: T, fromIndex?: number): number | indexOf(searchElement: T, fromIndex?: number): number | 否 | / | -| forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void | forEach(callbackFn: (value: T, index: number, array: Array<T>) => void): void | 是 | ArkTS不支持this,因此不支持thisArg参数。 | -| map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] | map<U>(callbackFn: (value: T, index: number, array: Array<T>) => U): Array<U> | 是 | ArkTS不支持this,因此不支持thisArg参数。 | -| filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[] | filter(predicate: (value: T, index: number, array: Array<T>) => boolean): Array<T> | 是 | ArkTS不支持this,因此不支持thisArg参数。 | +| forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void | forEach(callbackFn: (value: T, index: number, array: Array<T>) => void): void | 是 | ArkTS不支持this,因此不支持thisArg参数。| +| map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] | map<U>(callbackFn: (value: T, index: number, array: Array<T>) => U): Array<U> | 是 | ArkTS不支持this,因此不支持thisArg参数。| +| filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[] | filter(predicate: (value: T, index: number, array: Array<T>) => boolean): Array<T> | 是 | ArkTS不支持this,因此不支持thisArg参数。| | reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T | reduce(callbackFn: (previousValue: T, currentValue: T, currentIndex: number, array: Array<T>) => T): T | 否 | / | | reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U | reduce<U>(callbackFn: (previousValue: U, currentValue: T, currentIndex: number, array: Array<T>) => U, initialValue: U): U | 否 | / | -| [n: number]: T | [index: number]: T | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number | findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean): number | 是 | ArkTS不支持this,因此不支持thisArg参数。 | -| fill(value: T, start?: number, end?: number): this | fill(value: T, start?: number, end?: number): Array<T> | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。 | +| [n: number]: T | [index: number]: T | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number | findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean): number | 是 | ArkTS不支持this,因此不支持thisArg参数。| +| fill(value: T, start?: number, end?: number): this | fill(value: T, start?: number, end?: number): Array<T> | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。| | entries(): IterableIterator<[number, T]> | entries(): IterableIterator<[number, T]> | 否 | / | | keys(): IterableIterator<number> | keys(): IterableIterator<number> | 否 | / | | values(): IterableIterator<T> | values(): IterableIterator<T> | 否 | / | @@ -105,17 +105,17 @@ ArkTS提供了Sendable数据相关的共享容器集,接口行为与原生API | at(index: number): T \| undefined | at(index: number): T \| undefined | 否 | / | | isArray(arg: any): arg is any[] | static isArray(value: Object \| undefined \| null): boolean | 是 | 仅判断是否为ArkTS的Array实例,对原生容器Array返回false。| | of<T>(...items: T[]): T[] | static of<T>(...items: T[]): Array<T> | 否 | / | -| copyWithin(target: number, start: number, end?: number): this | copyWithin(target: number, start: number, end?: number): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| lastIndexOf(searchElement: T, fromIndex?: number): number | lastIndexOf(searchElement: T, fromIndex?: number): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean | some(predicate: ArrayPredicateFn<T, Array<T>>): boolean | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2.ArkTS不支持this,因此不支持thisArg参数。| -| reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T | reduceRight(callbackFn: ArrayReduceCallback<T, T, Array<T>>): T | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U | reduceRight<U = T>(callbackFn: ArrayReduceCallback<U, T, Array<T>>, initialValue: U): U | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| reverse(): T[] | reverse(): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | -| toString(): string | toString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| copyWithin(target: number, start: number, end?: number): this | copyWithin(target: number, start: number, end?: number): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| lastIndexOf(searchElement: T, fromIndex?: number): number | lastIndexOf(searchElement: T, fromIndex?: number): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean | some(predicate: ArrayPredicateFn<T, Array<T>>): boolean | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。| +| reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T | reduceRight(callbackFn: ArrayReduceCallback<T, T, Array<T>>): T | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U | reduceRight<U = T>(callbackFn: ArrayReduceCallback<U, T, Array<T>>, initialValue: U): U | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| reverse(): T[] | reverse(): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| toString(): string | toString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| | find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T \| undefined | find(predicate: (value: T, index: number, obj: Array<T>) => boolean): T \| undefined | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。| -| splice(start: number, deleteCount: number, ...items: T[]): T[] | splice(start: number, deleteCount: number, ...items: T[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| splice(start: number, deleteCount: number, ...items: T[]): T[] | splice(start: number, deleteCount: number, ...items: T[]): Array<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| | every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean | every(predicate: ArrayPredicateFn<T, Array<T>>): boolean | 是 | ArkTS不支持this,因此不支持thisArg参数。| -| toLocaleString(): string | toLocaleString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| toLocaleString(): string | toLocaleString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| ### ArrayBuffer @@ -127,7 +127,7 @@ ArkTS提供了Sendable数据相关的共享容器集,接口行为与原生API ### TypedArray(以Int8Array为例) -支持原生容器TypedArray通过[collections.TypedArray.from](../reference/apis-arkts/js-apis-arkts-collections.md#from-1)方法转换为ArkTS TypedArray容器;支持通过原生容器TypedArray的from方法将ArkTS TypedArray容器转换为原生容器TypedArray。 +支持原生容器TypedArray通过 `collections.TypedArray.from` 方法转换为 ArkTS TypedArray 容器;支持 ArkTS TypedArray 容器通过 `TypedArray.from` 方法转换为原生容器TypedArray。 | 原生API方法 | ArkTS容器集方法 | 是否有行为差异 | 在ArkTS容器中的差异表现 | | -------- | -------- | -------- | -------- | @@ -136,26 +136,26 @@ ArkTS提供了Sendable数据相关的共享容器集,接口行为与原生API | readonly byteOffset: number | readonly byteOffset: number | 否 | / | | readonly length: number | readonly length: number | 否 | / | | readonly BYTES_PER_ELEMENT: number | static readonly BYTES_PER_ELEMENT: number | 否 | / | -| copyWithin(target: number, start: number, end?: number): this | copyWithin(target: number, start: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| every(predicate: (value: number, index: number, array: Int8Array) => unknown, thisArg?: any): boolean | every(predicate: TypedArrayPredicateFn<number, Int8Array>): boolean | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | -| fill(value: number, start?: number, end?: number): this | fill(value: number, start?: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| filter(predicate: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array | filter(predicate: TypedArrayPredicateFn<number, Int8Array>): Int8Array | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | -| find(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number \| undefined | find(predicate: TypedArrayPredicateFn<number, Int8Array>): number \| undefined | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | -| findIndex(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number | findIndex(predicate: TypedArrayPredicateFn<number, Int8Array>): number | 是 | ArkTS不支持this,因此不支持thisArg参数。 | -| forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void | forEach(callbackFn: (value: number, index: number, array: Int8Array) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| copyWithin(target: number, start: number, end?: number): this | copyWithin(target: number, start: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。| +| every(predicate: (value: number, index: number, array: Int8Array) => unknown, thisArg?: any): boolean | every(predicate: TypedArrayPredicateFn<number, Int8Array>): boolean | 是 | 1. 在遍历、访问过程中,不允许进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| fill(value: number, start?: number, end?: number): this | fill(value: number, start?: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| filter(predicate: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array | filter(predicate: TypedArrayPredicateFn<number, Int8Array>): Int8Array | 是 | 1. 在遍历、访问过程中,不允许进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| find(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number \| undefined | find(predicate: TypedArrayPredicateFn<number, Int8Array>): number \| undefined | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| `findIndex(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number` | `findIndex(predicate: TypedArrayPredicateFn): number` | 是 | ArkTS 不支持 `thisArg` 参数。 | +| forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void | forEach(callbackFn: (value: number, index: number, array: Int8Array) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | | indexOf(searchElement: number, fromIndex?: number): number | indexOf(searchElement: number, fromIndex?: number): number | 否 | / | | join(separator?: string): string | join(separator?: string): string | 否 | / | -| map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array | map(callbackFn: TypedArrayForEachCallback<number, Int8Array>): Int8Array | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array | map(callbackFn: TypedArrayForEachCallback<number, Int8Array>): Int8Array | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | | reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number | reduce(callbackFn: TypedArrayReduceCallback<number, number, Int8Array>): number | 否 | / | | reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number | reduce(callbackFn: TypedArrayReduceCallback<number, number, Int8Array>, initialValue: number): number | 否 | / | | reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U | reduce<U>(callbackFn: TypedArrayReduceCallback<U, number, Int8Array>, initialValue: U): U | 否 | / | | reverse(): Int8Array | reverse(): Int8Array | 否 | / | -| set(array: ArrayLike<number>, offset?: number): void | set(array: ArrayLike<number>, offset?: number): void | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| set(array: ArrayLike<number>, offset?: number): void | set(array: ArrayLike<number>, offset?: number): void | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | | slice(start?: number, end?: number): Int8Array | slice(start?: number, end?: number): Int8Array | 否 | / | | some(predicate: (value: number, index: number, array: Int8Array) => unknown, thisArg?: any): boolean | some(predicate: TypedArrayPredicateFn<number, Int8Array>): boolean | 是 | ArkTS不支持this,因此不支持thisArg参数。 | -| sort(compareFn?: (a: number, b: number) => number): this | sort(compareFn?: TypedArrayCompareFn<number>): Int8Array | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。 | -| subarray(begin?: number, end?: number): Int8Array | subarray(begin?: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| [index: number]: number | [index: number]: number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| sort(compareFn?: (a: number, b: number) => number): this | sort(compareFn?: TypedArrayCompareFn<number>): Int8Array | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. 继承场景下,无法获得实际类型的返回值。 | +| subarray(begin?: number, end?: number): Int8Array | subarray(begin?: number, end?: number): Int8Array | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| [index: number]: number | [index: number]: number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | | entries(): IterableIterator<[number, number]> | entries(): IterableIterator<[number, number]> | 否 | / | | keys(): IterableIterator<number> | keys(): IterableIterator<number> | 否 | / | | values(): IterableIterator<number> | values(): IterableIterator<number> | 否 | / | @@ -168,39 +168,39 @@ ArkTS提供了Sendable数据相关的共享容器集,接口行为与原生API | from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Int8Array | static from<T>(arrayLike: ArrayLike<T>, mapFn: TypedArrayFromMapFn<T, number>): Int8Array | 是 | ArkTS不支持this,因此不支持thisArg参数。 | | from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array | static from(arrayLike: Iterable<number>, mapFn?: TypedArrayFromMapFn<number, number>): Int8Array | 是 | ArkTS不支持this,因此不支持thisArg参数。 | | of(...items: number[]): Int8Array | static of(...items: number[]): Int8Array | 否 | / | -| toString(): string | toString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| toLocaleString(): string | toLocaleString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| lastIndexOf(searchElement: number, fromIndex?: number): number | lastIndexOf(searchElement: number, fromIndex?: number): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number | reduceRight(callbackFn: TypedArrayReduceCallback<number, number, Int8Array>): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U | reduceRight<U = number>(callbackFn: TypedArrayReduceCallback<U, number, Int8Array>, initialValue: U): U | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| toString(): string | toString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| toLocaleString(): string | toLocaleString(): string | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| lastIndexOf(searchElement: number, fromIndex?: number): number | lastIndexOf(searchElement: number, fromIndex?: number): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number | reduceRight(callbackFn: TypedArrayReduceCallback<number, number, Int8Array>): number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U | reduceRight<U = number>(callbackFn: TypedArrayReduceCallback<U, number, Int8Array>, initialValue: U): U | 是 | 在遍历或访问过程中,不允许进行元素的增、删、改操作,否则会抛出异常。 | ### Map | 原生API方法 | ArkTS容器集方法 | 是否有行为差异 | 在ArkTS容器中的差异表现 | | -------- | -------- | -------- | -------- | -| readonly size: number | readonly size: number | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| clear(): void | clear(): void | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| delete(key: K): boolean | delete(key: K): boolean | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void | forEach(callbackFn: (value: V, key: K, map: Map<K, V>) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | -| get(key: K): V \| undefined | get(key: K): V \| undefined | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| has(key: K): boolean | has(key: K): boolean | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| set(key: K, value: V): this | set(key: K, value: V): Map<K, V> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| readonly size: number | readonly size: number | 是 | 在遍历或访问过程中,不允许进行元素的增、删、改操作,否则会抛出异常。 | +| clear(): void | clear(): void | 是 | 不允许在遍历或访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| delete(key: K): boolean | delete(key: K): boolean | 是 | 不允许在遍历或访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void | forEach(callbackFn: (value: V, key: K, map: Map<K, V>) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| get(key: K): V \| undefined | get(key: K): V \| undefined | 是 | 不允许在遍历或访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| has(key: K): boolean | has(key: K): boolean | 是 | 不允许在遍历或访问过程中进行元素的增加、删除或修改操作,否则会抛出异常。 | +| set(key: K, value: V): this | set(key: K, value: V): Map | 是 | 不允许在遍历或访问过程中进行元素的增删改操作,否则会抛出异常。 | | entries(): IterableIterator<[K, V]> | entries(): IterableIterator<[K, V]> | 否 | / | | keys(): IterableIterator<K> | keys(): IterableIterator<K> | 否 | / | | values(): IterableIterator<V> | values(): IterableIterator<V> | 否 | / | -| new <K, V>(entries?: readonly (readonly [K, V])[] \| null): Map<K, V> | constructor(entries?: readonly (readonly [K, V])[] \| null) | 是 | 构造时传入的k,v键值不能是非Sendable数据,否则编译会报错。 | +| new <K, V>(entries?: readonly (readonly [K, V])[] \| null): Map<K, V> | constructor(entries?: readonly (readonly [K, V])[] \| null) | 是 | 构造时传入的键值必须是Sendable数据,否则编译会报错。 | ### Set | 原生API方法 | ArkTS容器集方法 | 是否有行为差异 | 在ArkTS容器中的差异表现 | | -------- | -------- | -------- | -------- | -| readonly size: number | readonly size: number | 是 | Sendable类和接口中不允许使用计算属性名称(arkts-sendable-compated-prop-name)。 | -| add(value: T): this | add(value: T): Set<T> | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| readonly size: number | readonly size: number | 是 | 构造时传入的数据必须是Sendable类型,否则编译会报错。 | +| add(value: T): this | add(value: T): Set | 是 | 在遍历或访问过程中,不允许进行元素的增、删、改操作,否则会抛出异常。 | | clear(): void | clear(): void | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| delete(value: T): boolean | delete(value: T): boolean | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | -| forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void | forEach(callbackFn: (value: T, value2: T, set: Set<T>) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | -| has(value: T): boolean | has(value: T): boolean | 是 | 不允许在遍历、访问过程中进行元素的增、删、改操作否则会抛出异常。 | +| delete(value: T): boolean | delete(value: T): boolean | 是 | 不允许在遍历或访问过程中进行元素的增、删、改操作,否则会抛出异常。 | +| forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void | forEach(callbackFn: (value: T, value2: T, set: Set<T>) => void): void | 是 | 1. 不允许在遍历、访问过程中进行元素的增、删、改操作,否则会抛出异常。
2. ArkTS不支持this,因此不支持thisArg参数。 | +| has(value: T): boolean | has(value: T): boolean | 是 | 不允许在遍历或访问过程中进行元素的增、删、改操作,否则会抛出异常。 | | entries(): IterableIterator<[T, T]> | entries(): IterableIterator<[T, T]> | 否 | / | | keys(): IterableIterator<T> | keys(): IterableIterator<T> | 否 | / | -| values(): IterableIterator<T> | values(): IterableIterator<T> | 是 | Sendable类和接口中不允许使用计算属性名称(arkts-sendable-compated-prop-name)。 | +| values(): IterableIterator<T> | values(): IterableIterator<T> | 是 | 构造时传入的数据必须是Sendable类型,否则编译会报错。 | | new <T = any>(values?: readonly T[] \| null): Set<T> | constructor(values?: readonly T[] \| null) | 是 | 构造时传入的数据必须是Sendable类型,否则编译会报错。 | diff --git a/zh-cn/application-dev/arkts-utils/arkts-condition-variable-introduction.md b/zh-cn/application-dev/arkts-utils/arkts-condition-variable-introduction.md index 1effbab5905..b220423e9c1 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-condition-variable-introduction.md +++ b/zh-cn/application-dev/arkts-utils/arkts-condition-variable-introduction.md @@ -1,12 +1,12 @@ # 异步等待 -ArkTS引入了异步等待通知能力,以解决多线程任务时序控制问题。异步等待通知[ConditionVariable](../reference/apis-arkts/js-apis-arkts-utils.md#conditionvariable18)对象支持跨线程引用传递。 +ArkTS引入了异步等待通知能力,以解决多线程任务时序控制问题。异步等待通知能力[ConditionVariable](../reference/apis-arkts/js-apis-arkts-utils.md#conditionvariable18)支持跨线程引用传递。 -由于ArkTS语言支持异步操作,现在增加了异步任务的等待和被唤醒功能。当收到唤醒通知或等待超时后,异步任务将继续执行。 +ArkTS语言支持异步操作,增加了异步任务的等待和被唤醒功能。收到唤醒通知或等待超时后,异步任务将继续执行。 > **说明:** > -> 使用异步等待的方法需标记为async,调用时需用await修饰,以确保时序正确。 +> 使用异步等待通知的方法需标记为async。调用时需用await修饰,以确保时序正确。 ## 使用示例 diff --git a/zh-cn/application-dev/arkts-utils/arkts-sendable-module.md b/zh-cn/application-dev/arkts-utils/arkts-sendable-module.md index bfd9acf7aa5..b4e3a5da468 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-sendable-module.md +++ b/zh-cn/application-dev/arkts-utils/arkts-sendable-module.md @@ -2,23 +2,23 @@ 共享模块是进程内只会加载一次的模块,使用"use shared"这一指令来标记一个模块是否为共享模块。 -非共享模块在同一线程内只加载一次,而在不同线程中会加载多次,每个线程都会生成新的模块对象。因此,可以使用共享模块来实现进程单例。 +非共享模块在同一线程内仅加载一次,而在不同线程中会多次加载,每个线程生成新的模块对象。因此,使用共享模块可实现进程单例。 ## 约束限制 - "use shared"需要与"use strict"一样写在ArkTS文件顶层,写在import语句之后其他语句之前。 - 共享属性不具备传递性。非共享模块A即使引入了共享模块B,模块A也不会因此变成共享模块。 +共享属性不具备传递性。非共享模块A即使引入了共享模块B,模块A也不会因此变成共享模块。 - 共享模块只支持ets文件。 - 共享模块内不允许使用side-effects-import。 - 共享模块在同一进程内只加载一次,可在不同线程间共享。
- 共享模块加载时,导入的非共享模块不会立刻加载。在共享模块内访问依赖的非共享模块导出变量时,会在当前线程懒加载对应的非共享模块,非共享模块在线程间是隔离的,不同线程访问时会进行至多一次的模块懒加载。
- 由于side-effects-import不涉及导出变量,所以永远不会被加载,因此不支持。 + 共享模块在同一进程内仅加载一次,可在不同线程间共享。
+ 共享模块加载时,导入的非共享模块不会立即加载。在共享模块内访问依赖的非共享模块导出变量时,会在当前线程懒加载对应的非共享模块。非共享模块在线程间是隔离的,不同线程访问时会进行至多一次的模块懒加载。
+ 由于side-effects-import不涉及导出变量,因此永远不会被加载,不支持此功能。 ```ts // 不允许使用side-effects-import @@ -27,7 +27,7 @@ - 共享模块导出的变量必须是可共享对象。 - 共享模块在并发实例间可共享,因此共享模块导出的所有对象必须是可共享的,可共享对象参考[Sendable支持的数据类型](arkts-sendable.md#sendable支持的数据类型)。 + 共享模块在并发实例间可共享,导出的所有对象必须是可共享的。可共享对象参考[Sendable支持的数据类型](arkts-sendable.md#sendable支持的数据类型)。 - 共享模块不允许直接导出模块。 @@ -46,9 +46,9 @@ ``` -- 共享模块可以引用共享模块或非共享模块。共享模块的引用和被引用场景没有限制。 +- 共享模块可以引用共享模块或非共享模块。引用和被引用场景没有限制。 -- 仅支持使用静态加载、napi_load_module或napi_load_module_with_info加载共享模块。 +- 仅支持静态加载、`napi_load_module` 和 `napi_load_module_with_info` 加载共享模块。 ```ts // test.ets import { num } from './A'; // 支持静态加载 @@ -70,7 +70,7 @@ // 共享模块sharedModule.ets import { ArkTSUtils } from '@kit.ArkTS'; - // 声明当前模块为共享模块,只能导出可Sendable数据 + // 声明当前模块为共享模块,只能导出可Sendable的数据。 "use shared" // 共享模块,SingletonA全局唯一 diff --git a/zh-cn/application-dev/arkts-utils/arkts-sendable.md b/zh-cn/application-dev/arkts-utils/arkts-sendable.md index 89ec39178b0..ce3988df086 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-sendable.md +++ b/zh-cn/application-dev/arkts-utils/arkts-sendable.md @@ -1,42 +1,42 @@ # Sendable对象简介 -在传统JS引擎中,优化对象的并发通信开销的唯一方法是将实现下沉到Native侧,通过[Transferable对象](transferabled-object.md)的转移或共享来降低并发通信开销。但开发者仍有大量对象并发通信的需求,这个问题在业界JS引擎中未得到解决。 +在传统JS引擎中,优化对象并发通信开销的唯一方法是将实现下沉到Native侧,通过Transferable对象的转移或共享来降低开销。然而,开发者仍有大量对象并发通信的需求,这一问题在业界JS引擎中尚未解决。 ArkTS提供了Sendable对象类型,在并发通信时支持通过引用传递来解决上述问题。 -Sendable对象为可共享的,其跨线程前后指向同一个JS对象。如果包含JS或Native内容,可以直接共享。如果底层是Native实现,则需要考虑线程安全性。通信过程如下图所示: +Sendable对象可跨线程共享,始终指向同一个JS对象。若包含JS或Native内容,可直接共享。若底层为Native实现,需确保线程安全。通信过程如下图所示: ![sendable](figures/sendable.png) -与其它ArkTS数据对象不同,符合Sendable协议的数据对象在运行时应为类型固定的对象。 +符合Sendable协议的数据对象在运行时必须是类型固定的对象,与其他ArkTS数据对象不同。 -当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争,例如[ArkTS共享容器](arkts-collections-introduction.md)的多线程操作。因此,ArkTS提供[异步锁](arkts-async-lock-introduction.md)机制来避免不同并发实例间的数据竞争,并提供了[异步等待](arkts-condition-variable-introduction.md)机制来控制多线程处理数据的时序。同时,还可以通过[对象冻结接口](sendable-freeze.md)将对象冻结为只读,从而避免数据竞争问题。 +当多个并发实例同时更新Sendable数据时,会发生数据竞争。例如,ArkTS共享容器的多线程操作。因此,ArkTS提供异步锁机制来避免数据竞争,并提供异步等待机制来控制多线程处理数据的时序。此外,还可以通过对象冻结接口将对象冻结为只读,从而避免数据竞争。 -Sendable对象提供了并发实例间高效的通信能力,即引用传递,适用于开发者自定义大对象需要线程间通信的场景,例如子线程读取数据库数据并返回给宿主线程,具体代码实现可参考[跨并发实例传输大数据场景](sendable-guide.md#跨并发实例传输大数据场景)。 +Sendable对象提供并发实例间高效的通信能力,适用于大对象的线程间通信,例如子线程读取数据库数据并返回给宿主线程。具体代码实现可参考[跨并发实例传输大数据场景](sendable-guide.md#跨并发实例传输大数据场景)。 ## 基础概念 ### Sendable协议 Sendable协议定义了ArkTS的可共享对象体系及其规格约束。符合Sendable协议的数据(以下简称Sendable对象)可以在ArkTS并发实例间传递。 -默认情况下,Sendable数据在ArkTS并发实例间(包括UI主线程、TaskPool线程、Worker线程)传递的行为是引用传递。同时,ArkTS也支持Sendable数据在这些实例间拷贝传递。 +默认情况下,Sendable 数据在 ArkTS 并发实例间(包括 UI 主线程、TaskPool 线程、Worker 线程)以引用方式传递。ArkTS 还支持这些实例间的数据拷贝传递。 ### ISendable -在ArkTS语言基础库[@arkts.lang](../reference/apis-arkts/js-apis-arkts-lang.md)中引入了interface ISendable,没有任何必须的方法或属性。ISendable是所有Sendable类型(除了null和undefined)的父类型。ISendable主要用在开发者自定义Sendable数据结构的场景中。类装饰器[@Sendable装饰器](#sendable装饰器)是implement ISendable的语法糖。 +ArkTS语言基础库[@arkts.lang](../reference/apis-arkts/js-apis-arkts-lang.md)引入了ISendable接口,没有必须的方法或属性。ISendable是所有Sendable类型的父类型。ISendable用于自定义Sendable数据结构,类装饰器[@Sendable装饰器](#sendable装饰器)是实现ISendable的语法糖。 ### Sendable class -> **说明:** +> **说明** > > 从API version 11开始,支持使用\@Sendable装饰器校验Sendable class。 -Sendable class需同时满足以下两个规则: +Sendable class需满足以下规则: -1. 当且仅当被标注了[@Sendable装饰器](#sendable装饰器)。 +1. 当被标注了[@Sendable装饰器](#sendable装饰器)。 -2. 需满足Sendable约束,详情可查[Sendable使用规则](sendable-constraints.md)。 +2. 需满足Sendable约束,详情见[Sendable使用规则](sendable-constraints.md)。 ### Sendable function @@ -48,83 +48,83 @@ Sendable class需同时满足以下两个规则: > > - 针对API version大于12的工程,开发者可直接使用\@Sendable装饰器校验Sendable function,无需再进行其他配置。 -Sendable function需同时满足以下两个规则: +Sendable function需满足以下规则: -1. 当且仅当被标注了[@Sendable装饰器](#sendable装饰器)。 +1. 当被标注为[@Sendable装饰器](#sendable装饰器)。 -2. 需满足Sendable约束,详情可查[Sendable使用规则](sendable-constraints.md)。 +2. 需满足Sendable约束,具体参见[Sendable使用规则](sendable-constraints.md)。 -### Sendable interface +### Sendable class -Sendable interface需同时满足以下两个规则: +Sendable class需同时满足以下两个规则: -1. 当且仅当是[ISendable](#isendable)或者继承了ISendable。 +1. 是[ISendable](#isendable)或其子类。 -2. 需满足Sendable约束,详情可查[Sendable使用规则](sendable-constraints.md)。 +2. 需满足Sendable约束,详情参见[Sendable使用规则](sendable-constraints.md)。 -### Sendable支持的数据类型 +### Sendable class 支持的数据类型 - ArkTS基本数据类型:boolean、number、string、bigint、null、undefined。 -- ArkTS语言标准库中定义的[容器类型数据](arkts-collections-introduction.md)(须显式引入[@arkts.collections](../reference/apis-arkts/js-apis-arkts-collections.md))。 +ArkTS语言标准库中定义的容器类型数据(需显式引入[@arkts.collections])。 -- ArkTS语言标准库中定义的[异步锁对象](arkts-async-lock-introduction.md)(须显式引入[@arkts.utils](../reference/apis-arkts/js-apis-arkts-utils.md))。 +ArkTS语言标准库中定义的异步锁对象(需显式引入[@arkts.utils])。 -- ArkTS语言标准库中定义的[异步等待对象](arkts-condition-variable-introduction.md)(须显式引入[@arkts.utils](../reference/apis-arkts/js-apis-arkts-utils.md))。 +ArkTS语言标准库中定义的异步等待对象(需显式引入`@arkts.utils`)。 -- 继承了[ISendable](#isendable)的interface。 +继承了[ISendable](#isendable)的接口。 -- 标注了[@Sendable装饰器](#sendable装饰器)的class。 +标注了`@Sendable`装饰器的类。 -- 标注了[@Sendable装饰器](#sendable装饰器)的function。 +标注了`@Sendable`装饰器的函数。 -- 接入Sendable的系统对象。 +- 接入了Sendable的系统对象。 - [共享用户首选项](../reference/apis-arkdata/js-apis-data-sendablePreferences.md) - [可共享的色彩管理](../reference/apis-arkgraphics2d/js-apis-sendableColorSpaceManager.md) - [基于Sendable对象的图片处理](../reference/apis-image-kit/js-apis-sendableImage.md) - [资源管理](../reference/apis-localization-kit/js-apis-sendable-resource-manager.md) - [SendableContext对象管理](../reference/apis-ability-kit/js-apis-app-ability-sendableContextManager.md) -- 元素均为Sendable类型的union type数据。 +- 元素均为Sendable类型的联合类型数据。 > **说明:** > -> - JS内置对象在并发实例间的传递遵循结构化克隆算法,跨线程行为是拷贝传递。因此,JS内置对象的实例不是Sendable类型。 +> - JS内置对象在并发实例间传递时遵循结构化克隆算法,跨线程行为是拷贝传递。因此,JS内置对象的实例不是Sendable类型。 > -> - 对象字面量、数组字面量在并发实例间的传递遵循结构化克隆算法,跨线程行为是拷贝传递。因此,对象字面量和数组字面量不是Sendable类型。 +> - 对象字面量和数组字面量在并发实例间传递时遵循结构化克隆算法,跨线程行为是拷贝传递。因此,对象字面量和数组字面量不是Sendable类型。 ## Sendable的实现原理 -为了实现[Sendable数据](#sendable支持的数据类型)在不同并发实例间的引用传递,Sendable共享对象分配在共享堆中,实现跨并发实例的内存共享。 +为了在不同并发实例间传递Sendable数据,Sendable共享对象分配在共享堆中,实现内存共享。 -共享堆(SharedHeap)是进程级别的堆空间,与虚拟机本地堆(LocalHeap)不同的是,LocalHeap只能被单个并发实例访问,而SharedHeap可以被所有线程访问。一个Sendable对象的跨线程行为是引用传递。因此,一个Sendable对象可能被多个并发实例引用,判断该Sendable对象是否存活,取决于所有并发实例是否存在对此Sendable对象的引用。 +共享堆(SharedHeap)是进程级别的堆空间,与虚拟机本地堆(LocalHeap)不同,LocalHeap仅限单个并发实例访问,而SharedHeap可被所有线程访问。Sendable对象的跨线程行为是引用传递,因此可能被多个并发实例引用。Sendable对象是否存活取决于所有并发实例是否存在对该对象的引用。 **SharedHeap与LocalHeap关系图** ![zh-cn_image_0000002001521153](figures/zh-cn_image_0000002001521153.png) -各个并发实例的LocalHeap是隔离的,SharedHeap是进程级别的堆,可以被所有并发实例引用,但SharedHeap不能引用LocalHeap中的对象。 +各个并发实例的LocalHeap相互隔离,SharedHeap为进程级别的堆,可被所有并发实例引用,但不能引用LocalHeap中的对象。 ## \@Sendable装饰器 -声明并校验Sendable class以及Sendable function。 +声明并校验Sendable类和Sendable函数。 | \@Sendable装饰器 | 说明 | | -------- | -------- | | 装饰器参数 | 无。 | | 使用场景限制 | 仅支持在Stage模型的.ets文件中使用。 | -| 装饰的函数类型限制 | 仅支持装饰普通function和Async function类型。 | -| 装饰的类继承关系限制 | Sendable class只能继承Sendable class,普通Class不可以继承Sendable class。 | -| 装饰的对象内的属性类型限制 | 1. 支持string、number、boolean、bigint、null、undefined、Sendable class、collections.Array、collections.Map、collections.Set、ArkTSUtils.locks.AsyncLock、ArkTSUtils.SendableLruCache以及自定义的Sendable函数类型。
2. 禁止使用闭包变量。
3. 不支持通过\#定义私有属性,需用private。
4. 不支持计算属性。 | -| 装饰的对象内的属性的其他限制 | 成员属性必须显式初始化,不能使用感叹号。 | -| 装饰的函数或类对象内的方法参数限制 | 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量,定义在顶层的Sendable class和Sendable function除外。从API version 18开始,支持访问本文件导出的变量。 | -| Sendable Class及Sendable Function的限制 | 不支持增加或删除属性,允许修改属性,修改前后属性的类型必须一致,不支持修改方法。 | -| 适用场景 | 1. 在TaskPool或Worker中使用类方法/Sendable函数。
2. 传输对象数据量较大的使用场景。序列化耗时会随着数据量增大而增大,使用Sendable对数据改造后传输100KB数据时效率提升约20倍,传输1M数据时效率提升约100倍。 | +| 装饰的函数类型限制 | 仅支持装饰普通函数和异步函数类型。 | +| 装饰的类继承关系限制 | Sendable 类只能继承Sendable 类,普通类不可以继承Sendable 类。 | +| 装饰对象的属性类型限制 | 1. 支持的属性类型包括:`string`、`number`、`boolean`、`bigint`、`null`、`undefined`、`Sendable 类`、`collections.Array`、`collections.Map`、`collections.Set`、`ArkTSUtils.locks.AsyncLock`、`ArkTSUtils.SendableLruCache` 以及自定义的 `Sendable` 函数类型。
2. 禁用闭包变量。
3. 不支持使用 `#` 定义私有属性,必须使用 `private`。
4. 不支持计算属性。 | +| 装饰的对象内的属性的其他限制 | 成员属性必须显式初始化。 | +| 装饰的函数或类方法参数限制 | 仅限使用局部变量、入参和导入的变量。禁止使用闭包变量,但顶层定义的Sendable类和Sendable函数除外。API版本18起,支持访问本文件导出的变量。 | +| Sendable Class和Sendable Function的限制 | 不允许增加或删除属性,允许修改属性,但修改前后属性的类型必须一致,不支持修改方法。 | +| 适用场景 | 1. 在TaskPool或Worker中使用类方法或Sendable函数。
2. 大数据量传输场景。序列化耗时随数据量增大而增加,使用Sendable改造后传输100KB数据时效率提升约20倍,传输1M数据时效率提升约100倍。 | -**装饰器修饰Class使用示例:** +**使用装饰器修饰Class:** ```ts @Sendable @@ -140,7 +140,7 @@ class SendableTestClass { } ``` -**装饰器修饰Function使用示例:** +**使用装饰器修饰Function:** ```ts @Sendable diff --git a/zh-cn/application-dev/arkts-utils/arraybuffer-object.md b/zh-cn/application-dev/arkts-utils/arraybuffer-object.md index 7eee9c4582c..3aa80115023 100644 --- a/zh-cn/application-dev/arkts-utils/arraybuffer-object.md +++ b/zh-cn/application-dev/arkts-utils/arraybuffer-object.md @@ -1,28 +1,28 @@ # ArrayBuffer对象 -ArrayBuffer由两部分组成:底层存储数据的Native内存区域,以及封装操作的JS对象壳,该JS对象壳被分配在虚拟机本地堆(LocalHeap)。跨线程传递时,JS对象壳需要经过序列化与反序列化拷贝传递,Native内存区域则有两种传递方式:拷贝和转移。 +ArrayBuffer由两部分组成:底层存储数据的Native内存区域,以及封装操作的JS对象壳。该JS对象壳被分配在虚拟机的本地堆(LocalHeap)。跨线程传递时,JS对象壳需要经过序列化与反序列化拷贝传递,而Native内存区域则有两种传递方式:拷贝和转移。 -采用拷贝方式(递归遍历),传输后两个线程可以独立访问ArrayBuffer。通信过程如下图所示: +采用拷贝方式(递归遍历)传输后,两个线程可以独立访问ArrayBuffer。通信过程如下图所示。 ![copy_transfer](figures/copy_transfer.png) -采用转移方式,传输后原线程将无法使用此ArrayBuffer对象。跨线程时只需重建JS壳,Native内存无需拷贝,效率更高。通信过程如下图所示: +采用转移方式传输后,原线程将无法使用此 ArrayBuffer 对象。跨线程时只需重建 JS 壳,Native 内存无需拷贝,效率更高。通信过程如下图所示。 ![transfer](figures/transfer.png) -ArrayBuffer可以用来表示图片等资源,在应用开发中,处理图片(如调整亮度、饱和度、大小等)时,为了避免阻塞UI主线程,可以将图片传递到子线程中进行处理。转移方式性能更高,但原线程无法再访问ArrayBuffer对象。如果两个线程都需要访问该对象,建议采用拷贝方式。否则,建议采用转移方式,以提升性能。 +在应用开发中,处理图片(如调整亮度、饱和度、大小等)时,为了避免阻塞UI主线程,可以将图片传递到子线程中进行处理。转移方式性能更高,但原线程无法再访问ArrayBuffer对象。如果两个线程都需要访问该对象,建议采用拷贝方式。否则,建议采用转移方式以提升性能。 下面将分别通过拷贝和转移的方式,将图片传递到子线程中。 ## ArrayBuffer拷贝传输方式 -在ArkTS中,TaskPool传递ArrayBuffer数据时,默认使用转移方式,通过调用setTransferList()接口,可以指定部分数据的传递方式为转移方式,而其他部分数据可以切换为拷贝方式。 +在ArkTS中,TaskPool传递ArrayBuffer数据时,默认使用转移方式。通过调用setTransferList()接口,可以指定部分数据使用转移方式,其他部分数据则使用拷贝方式。 -首先,实现一个处理ArrayBuffer的接口,该接口在Task中执行。 +实现一个处理ArrayBuffer的接口,该接口在Task中执行。 -然后,通过拷贝方式将ArrayBuffer数据传递到Task中,并处理。 +将ArrayBuffer数据通过拷贝方式传递到Task中,并进行处理。 -最后,UI主线程接收到Task执行完毕后返回的ArrayBuffer数据,拼接并展示。 +UI主线程接收到Task返回的ArrayBuffer数据,拼接并展示。 ```ts // Index.ets @@ -85,4 +85,4 @@ struct Index { ## ArrayBuffer转移传输方式 -在TaskPool中,传递ArrayBuffer数据时默认使用转移方式,原线程将无法再使用已传输给子线程的ArrayBuffer。在上文示例的基础上去除task.setTransferList接口调用,即在createImageTask的第二个参数传入true,就可以实现转移方式的传输。 +在ArkTS中传递ArrayBuffer数据时,默认使用转移方式,原线程将无法再使用已传输给子线程的ArrayBuffer。 若要实现转移方式的传输,可以在 `createImageTask` 的第二个参数传入 `true`,即去除 `task.setTransferList` 接口调用。 diff --git a/zh-cn/application-dev/arkts-utils/ason-parsing-generation.md b/zh-cn/application-dev/arkts-utils/ason-parsing-generation.md index f385442b5e0..6763158e678 100644 --- a/zh-cn/application-dev/arkts-utils/ason-parsing-generation.md +++ b/zh-cn/application-dev/arkts-utils/ason-parsing-generation.md @@ -1,12 +1,12 @@ -# ASON解析与生成 +# # ASON解析与生成 -[ASON工具](../reference/apis-arkts/js-apis-arkts-utils.md#arktsutilsason)与JS提供的JSON工具类似,JSON用于进行JS对象的序列化(stringify)、反序列化(parse)。ASON则提供了[Sendable对象](arkts-sendable.md)的序列化、反序列化能力。使用ASON.stringify方法可将对象转换为字符串,使用ASON.parse方法可将字符串转换为Sendable对象,从而实现对象在并发任务间的高性能引用传递。 +ASON工具与JS的JSON工具类似,用于对象的序列化和反序列化。ASON提供了Sendable对象的序列化和反序列化能力。使用ASON.stringify方法可将对象转换为字符串,使用ASON.parse方法可将字符串转换为Sendable对象,实现对象在并发任务间的高性能引用传递。 -ASON.stringify方法还支持将Map和Set对象转换为字符串,可转换的Map和Set类型包括:Map、Set、[collections.Map](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsmap)、[collections.Set](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsset)、[HashMap](../reference/apis-arkts/js-apis-hashmap.md#hashmap)、[HashSet](../reference/apis-arkts/js-apis-hashset.md#hashset)。 +ASON.stringify方法支持将Map和Set对象转换为字符串。支持的类型包括:Map、Set、collections.Map、collections.Set、HashMap、HashSet。 > **说明:** > -> ASON.parse默认生成的对象为Sendable对象,布局不可变,不支持增删属性。如果需要支持返回对象的布局可变,可以指定返回类型为MAP,此时会全部返回[collections.Map](../reference/apis-arkts/js-apis-arkts-collections.md#collectionsmap)对象,支持增删属性。 +> ASON.parse 默认生成 Sendable 对象,布局不可变,不支持添加和删除属性。若需布局可变,可指定返回类型为 Map,此时将返回 `collections.Map` 对象,支持添加和删除属性。 ## 使用示例 diff --git a/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md b/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md index b5fe4e2658a..6d025765fa3 100644 --- a/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md @@ -1,23 +1,23 @@ # 异步并发 (Promise和async/await) -Promise和async/await提供异步并发能力,是标准的JS异步语法。异步代码会被挂起并在之后继续执行,同一时间只有一段代码执行。以下是典型的异步并发使用场景: +Promise和async/await是标准的JS异步语法,允许程序在执行某些操作时不必等待其完成,可以继续执行其他操作。以下是典型的异步并发使用场景: -- I/O 非阻塞操作​​:网络请求、文件读写、定时器等。 +- I/O 非阻塞操作:网络请求、文件读写、定时器等。 -- 任务轻量且无 CPU 阻塞​​:单次任务执行时间短。 +- 任务轻量且无 CPU 阻塞:单次任务执行时间短。 -- 逻辑依赖清晰​​:任务有明确的顺序或并行关系。 +- 逻辑依赖清晰:任务有明确的顺序或并行关系。 -异步语法是一种编程语言的特性,允许程序在执行某些操作时不必等待其完成,可以继续执行其他操作。 +异步并发能力允许程序在执行某些操作时不必等待其完成,可以继续执行其他操作。 ## Promise -Promise是一种用于处理异步操作的对象,可以将异步操作转换为类似于同步操作的风格,以方便代码编写和维护。Promise提供了一个状态机制来管理异步操作的不同阶段,并提供了一些方法来注册回调函数以处理异步操作的成功或失败的结果。 +Promise用于处理异步操作,可以将异步操作转换为类似于同步操作的风格。Promise提供状态机制管理异步操作的不同阶段,并提供方法注册回调函数处理成功或失败的结果。 Promise有三种状态:pending(进行中)、fulfilled(已完成,也叫resolved)和rejected(已拒绝)。创建后处于pending状态,异步操作完成后转换为fulfilled或rejected。 -最基本的用法是通过构造函数实例化一个Promise对象,同时传入一个带有两个参数的函数,通常称为executor函数。executor函数接收两个参数:resolve和reject,分别表示异步操作成功和失败时的回调函数。例如,以下代码创建了一个Promise对象并模拟了一个异步操作: +通过构造函数实例化一个Promise对象,并传入一个带有两个参数的函数,通常称为executor函数。executor函数接收两个参数:resolve和reject,分别表示异步操作成功和失败时的回调函数。以下代码创建了一个Promise对象并模拟了一个异步操作: ```ts const promise: Promise = new Promise((resolve: Function, reject: Function) => { @@ -32,9 +32,9 @@ const promise: Promise = new Promise((resolve: Function, reject: Functio }) ``` -在上述代码中,setTimeout函数模拟了一个异步操作,1秒后生成一个随机数。如果随机数大于0.5,调用resolve回调函数并传递该随机数;否则调用reject回调函数并传递一个错误对象。 +setTimeout函数模拟异步操作,1秒后生成一个随机数。如果随机数大于0.5,调用resolve回调函数并传递该随机数。否则调用reject回调函数并传递一个错误对象。 -Promise对象创建后,可以使用then方法和catch方法指定fulfilled状态和rejected状态的回调函数。then方法可接受两个参数,一个处理fulfilled状态的函数,另一个处理rejected状态的函数。只传一个参数则表示当Promise对象状态变为fulfilled时,then方法会自动调用这个回调函数,并将Promise对象的结果作为参数传递给它。使用catch方法注册一个回调函数,用于处理“失败”的结果,即捕获Promise的状态改变为rejected状态或操作失败抛出的异常。例如: +Promise对象创建后,可以使用then方法和catch方法指定fulfilled状态和rejected状态的回调函数。then方法可接受两个参数:处理fulfilled状态的函数和处理rejected状态的函数。只传一个参数则表示处理fulfilled状态。使用catch方法注册回调函数,处理“失败”的结果。 ```ts import { BusinessError } from '@kit.BasicServicesKit'; @@ -55,7 +55,7 @@ promise.then((result: number) => { }); ``` -在上述代码中,then方法的回调函数接收Promise对象的成功结果作为参数,并输出到控制台。如果Promise对象进入rejected状态,catch方法的回调函数接收错误对象作为参数,并输出到控制台。 +then方法的回调函数接收Promise对象的成功结果,并输出到控制台。如果Promise对象进入rejected状态,catch方法的回调函数接收错误对象,并输出到控制台。 > **说明:** > @@ -63,11 +63,11 @@ promise.then((result: number) => { ## async/await -async/await是一种用于处理异步操作的Promise语法糖,使得编写异步代码变得更加简单和易读。通过使用async关键字声明一个函数为异步函数,并使用await关键字等待Promise的解析(完成或拒绝),以同步的方式编写异步操作的代码。 +async/await是Promise的语法糖,使得异步代码更简单易读。使用async关键字声明异步函数,并使用await关键字等待Promise解析。 -async函数通过返回Promise对象实现异步操作,其内部通过await关键字暂停执行直至关联的Promise完成状态转换(fulfilled/rejected)。若函数执行过程中抛出异常,该异常将直接触发返回的Promise进入rejected状态,错误对象可通过.catch()方法或then的第二个回调参数捕获。 +async函数返回Promise对象实现异步并发,内部通过await关键字暂停执行直至Promise完成状态转换。若函数执行过程中抛出异常,该异常将直接触发返回的Promise进入rejected状态,错误对象可通过.catch()方法或then的第二个回调参数捕获。 -下面是一个使用async/await的例子,其中模拟了一个以同步方式执行异步操作的场景,该操作会在3秒钟后返回一个字符串。 +下面是一个使用async/await的例子,模拟了以同步方式执行异步操作的场景。该操作会在3秒后返回一个字符串。 ```ts async function myAsyncFunction(): Promise { @@ -102,9 +102,9 @@ struct Index { } ``` -在上述示例代码中,使用了await关键字来等待Promise对象的解析,并将其解析值存储在result变量中。 +在上述代码中,使用await关键字等待Promise对象解析,并将其解析值存储在result变量中。 -需要注意的是,等待异步操作时,需将整个操作包在async函数中,并搭配await使用,同时也可使用try/catch块来捕获异步操作中的异常。 +等待异步操作时,需将操作包在async函数中,并搭配await使用。可使用try/catch块捕获异步操作中的异常。 ```ts async function myAsyncFunction(): Promise { diff --git a/zh-cn/application-dev/arkts-utils/batch-database-operations-guide.md b/zh-cn/application-dev/arkts-utils/batch-database-operations-guide.md index a1ebe3e1b85..fc0fbde295f 100644 --- a/zh-cn/application-dev/arkts-utils/batch-database-operations-guide.md +++ b/zh-cn/application-dev/arkts-utils/batch-database-operations-guide.md @@ -2,13 +2,13 @@ ## 使用TaskPool进行频繁数据库操作 -对于需要频繁数据库操作的场景,由于读写数据库存在耗时,因此推荐在子线程中操作,避免阻塞UI线程。 +对于需要频繁操作数据库的场景,推荐在子线程中执行读写操作,以避免阻塞UI线程。 -通过ArkTS提供的TaskPool能力,可以将数据库操作任务移到子线程中,实现如下。 +通过ArkTS提供的TaskPool能力,可以将数据库操作任务移到子线程中。 1. 创建多个子任务,支持数据库的创建、插入、查询和清除等操作。 -2. UI主线程调用子任务,完成数据库的增删改查等操作。 +2. UI主线程发起操作,子线程执行数据的增删改查。 ```ts // Index.ets @@ -141,9 +141,9 @@ struct Index { ## 使用Sendable进行大容量数据库操作 -由于数据库数据跨线程传递存在耗时,数据量较大时会占用UI主线程。推荐使用Sendable封装数据库数据,以降低跨线程开销。 +数据库数据跨线程传递耗时,数据量大时会占用UI主线程。推荐使用Sendable封装数据,以减少跨线程开销。 -1. 定义数据库中的数据格式,可以使用Sendable,以减少跨线程操作的耗时。 +1. 在子线程中定义数据库中的数据格式,使用Sendable以减少跨线程操作的耗时。 ```ts // SharedValuesBucket.ets @@ -309,13 +309,13 @@ struct Index { } ``` -## 复杂类实例对象使用Sendable进行大容量数据库操作 +## 使用Sendable进行大容量数据库操作 -普通类实例对象的属性可持有Sendable类实例对象。 +普通类实例对象的属性可以是Sendable类的实例。 -对于复杂的普通类实例对象,可以先将相应数据库数据字段封装为Sendable类实例对象,再由普通类实例对象持有,从而降低跨线程开销。 +对于复杂的类实例对象,可以先将数据库数据字段封装为Sendable类实例对象,再由该类实例对象持有,从而减少跨线程开销。 -1. 定义数据库中的数据格式,可采用Sendable,减少跨线程耗时。 +1. 定义数据库中的数据格式,采用Sendable以减少跨线程耗时。 ```ts // SharedValuesBucket.ets @@ -342,7 +342,7 @@ struct Index { } ``` -2. 定义普通类实例对象,持有Sendable类实例对象。 +2. 定义普通类实例对象,持有Sendable类实例。 ```ts // Material.ets @@ -371,7 +371,7 @@ struct Index { } ``` -3. UI主线程发起,在子线程进行数据的增删改查等操作。 +3. UI主线程发起操作,子线程执行数据的增删改查。 ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/concurrency-overview.md b/zh-cn/application-dev/arkts-utils/concurrency-overview.md index f243b8d7382..3fc9da0bc3e 100644 --- a/zh-cn/application-dev/arkts-utils/concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/concurrency-overview.md @@ -1,14 +1,14 @@ # 并发概述 -并发是指在同一时间内,存在多个任务同时执行的情况。对于多核设备,这些任务可以在不同CPU上并行执行。对于单核设备,尽管多个并发任务不会在同一时刻并行执行,但CPU会在某个任务休眠或进行I/O操作时切换任务,调度执行其他任务,从而提高CPU的资源利用率。 +并发是指在同一时间存在多个任务同时执行。在多核设备上,任务可在不同CPU上并行执行。在单核设备上,尽管多个任务不能同时并行,但CPU会在任务休眠或进行I/O操作时切换任务,调度执行其他任务,提高资源利用率。 -为了提升应用的响应速度与帧率,避免耗时任务影响UI主线程,ArkTS提供了异步并发和多线程并发两种处理策略。 +为了提升应用响应速度和帧率,避免耗时任务影响UI主线程,ArkTS提供异步并发和多线程并发两种处理策略。 -- 异步并发是指异步代码在执行到一定程度后会被暂停,以便在未来某个时间点继续执行,这种情况下,同一时间只有一段代码在执行。ArkTS通过Promise和async/await提供异步并发能力,适用于单次I/O任务的开发场景。详细请参见[使用异步并发能力](async-concurrency-overview.md)。 +- 异步并发指异步代码执行到一定程度后暂停,未来继续执行。同一时间只有一段代码执行。ArkTS通过Promise和async/await提供异步并发能力,适用于单次I/O任务。详细请参见[使用异步并发能力](async-concurrency-overview.md)。 -- 多线程并发允许在同一时间段内同时执行多段代码。在UI主线程继续响应用户操作和更新UI的同时,后台线程也能执行耗时操作,从而避免应用出现卡顿。ArkTS通过TaskPool和Worker提供多线程并发能力,适用于[耗时任务](time-consuming-task-overview.md)等并发场景。详细请参见[多线程并发概述](multi-thread-concurrency-overview.md)。 +- 多线程并发允许同时执行多段代码。UI主线程继续响应用户操作和更新UI,后台线程执行耗时操作,避免应用卡顿。ArkTS通过TaskPool和Worker提供多线程并发能力,适用于耗时任务等并发场景。详细请参见[多线程并发概述](multi-thread-concurrency-overview.md)。 -在并发多线程场景下,不同线程间需要进行数据通信。不同类别的对象采用不同的传输方式,如拷贝或内存共享。 +在并发多线程场景下,不同线程间需要进行数据通信。不同类别的对象采用不同的传输方式,例如拷贝或内存共享。 -并发能力广泛应用于多种场景,包括[异步并发任务](async-concurrency-overview.md)、[耗时任务](time-consuming-task-overview.md)(如[CPU密集型任务](cpu-intensive-task-development.md)、[I/O密集型任务](io-intensive-task-development.md)和[同步任务](sync-task-development.md)等)、[长时任务](long-time-task-overview.md)、[常驻任务](resident-task-overview.md)等。开发者可以根据不同的任务诉求和场景,选择相应的并发策略进行优化和开发,具体案例可以参见[应用多线程开发实践案例](batch-database-operations-guide.md)。 +并发能力适用于多种场景,包括异步并发任务、耗时任务(如CPU密集型任务、I/O密集型任务和同步任务)、长时任务、常驻任务等。根据任务需求和场景,选择相应的并发策略进行优化和开发。具体案例参见应用多线程开发实践案例。 diff --git a/zh-cn/application-dev/arkts-utils/concurrent-loading-modules-guide.md b/zh-cn/application-dev/arkts-utils/concurrent-loading-modules-guide.md index 07049874499..5155540417f 100644 --- a/zh-cn/application-dev/arkts-utils/concurrent-loading-modules-guide.md +++ b/zh-cn/application-dev/arkts-utils/concurrent-loading-modules-guide.md @@ -1,10 +1,10 @@ # 业务模块并发加载场景 -在应用启动过程中,会有多个业务模块需要加载,例如地图类应用的定位、打车、导航等不同的模块,如果全部在UI主线程初始化,则会严重影响冷启动耗时。此时需要在不同子线程并行化加载这些业务模块,降低启动耗时。 +应用启动时,多个业务模块需加载,如地图类应用的定位、打车、导航等。若全部在UI主线程初始化,将严重影响冷启动时间。应使用不同子线程并行加载这些模块,以减少启动耗时。 -通过使用ArkTS提供的TaskPool能力,可以将不同的业务初始化任务移到子线程中。业务模块可通过下沉C++实现为[NativeBinding对象](transferabled-object.md)或在ArkTS层定义为[Sendable对象](arkts-sendable.md),从而将初始化的模块返回给UI主线程调用,实现如下。 +使用ArkTS提供的TaskPool能力,将不同的业务初始化任务移到子线程中。业务模块可以通过下沉C++实现为[NativeBinding对象](transferabled-object.md),或在ArkTS层定义为[Sendable对象](arkts-sendable.md),从而将初始化模块返回给UI主线程调用。 -1. 各业务功能(SDK)模块定义(这里以Sendable对象为例)。 +1. 定义各业务功能(SDK)模块(这里以Sendable对象为例)。 计算器业务模块定义如下: ```ts @@ -59,12 +59,12 @@ private newCalc(opt: string, ret: string) { let newRecord = new collections.Array(opt, ret) - this.totalCount = this.history!.unshift(newRecord) + this.totalCount = this.history!.length } } ``` - 定时器业务模块定义如下: + 定义定时器业务模块。 ```ts // sdk/TimerSdk.ets @@ -85,13 +85,13 @@ } ``` -2. 在UI主线程触发各业务模块分发到子线程,加载完成后在UI主线程使用,示例如下: +2. 在UI主线程触发各业务模块分发到子线程,加载完成后在UI主线程使用。 ```ts // Index.ets import { Calculator } from '../sdk/Calculator' import { TimerSdk } from '../sdk/TimerSdk' - import { taskpool } from '@kit.ArkTS'; + import { TaskPool } from '@kit.ArkTS'; @Concurrent function initCalculator(): Calculator { @@ -110,10 +110,10 @@ timer?: TimerSdk aboutToAppear(): void { - taskpool.execute(initCalculator).then((ret) => { + TaskPool.execute(initCalculator).then((ret) => { this.calc = ret as Calculator }) - taskpool.execute(initTimerSdk).then((ret) => { + TaskPool.execute(initTimerSdk).then((ret) => { this.timer = ret as TimerSdk }) } diff --git a/zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md b/zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md index f67cf03683b..908a9a96a75 100644 --- a/zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md +++ b/zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md @@ -1,13 +1,13 @@ # CPU密集型任务开发指导 (TaskPool和Worker) -CPU密集型任务是指需要占用系统资源进行大量计算的任务,这类任务需要长时间运行,会阻塞线程中其他事件的处理,因此不适宜在UI主线程中进行。例如图像处理、视频编码、数据分析等。 +CPU密集型任务是指需要占用系统资源进行大量计算的任务,这类任务会阻塞线程中其他事件的处理,因此不适宜在UI主线程中进行。例如图像处理、视频编码、数据分析等。 -基于多线程并发机制处理CPU密集型任务可以提高CPU利用率,提升应用程序响应速度。 +多线程并发机制处理CPU密集型任务,提高CPU利用率,提升应用程序响应速度。 -当任务不需要长时间(3分钟)占据后台线程,而是一个个独立的任务时,推荐使用TaskPool,反之推荐使用Worker。 +当任务不需要长时间占据后台线程且为独立任务时,推荐使用TaskPool;反之,推荐使用Worker。 接下来将分别以图像直方图处理和后台长时间模型预测任务为例进行说明。 @@ -17,7 +17,7 @@ CPU密集型任务是指需要占用系统资源进行大量计算的任务, 1. 实现图像处理的业务逻辑。 2. 数据分段,通过任务组发起关联任务调度。 - 创建[TaskGroup](../reference/apis-arkts/js-apis-taskpool.md#taskgroup10),通过[addTask()](../reference/apis-arkts/js-apis-taskpool.md#addtask10)添加对应的任务,然后通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute10)执行任务组,并指定为[高优先级](../reference/apis-arkts/js-apis-taskpool.md#priority)。在当前任务组所有任务结束后,会将直方图处理结果同时返回。 + 创建[TaskGroup](../reference/apis-arkts/js-apis-taskpool.md#taskgroup10),通过[addTask()](../reference/apis-arkts/js-apis-taskpool.md#addtask10)添加任务,然后通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute10)执行任务组并指定为[高优先级](../reference/apis-arkts/js-apis-taskpool.md#priority)。任务组所有任务结束后,将直方图处理结果一并返回。 3. 结果数组汇总处理。 @@ -73,13 +73,13 @@ struct Index { ## 使用Worker进行长时间数据分析 -本文通过某地区提供的房价数据训练一个简易的房价预测模型,该模型支持通过输入房屋面积和房间数量去预测该区域的房价,模型需要长时间运行,房价预测需要使用前面的模型运行结果,因此需要使用Worker。 +本文使用某地区提供的房价数据训练一个简易的房价预测模型。该模型通过输入房屋面积和房间数量预测该区域的房价。模型运行时间较长,预测房价需使用模型的运行结果,因此采用Worker。 -1. DevEco Studio提供了Worker创建的模板,新建一个Worker线程,例如命名为“MyWorker”。 +1. DevEco Studio提供Worker创建模板,新建一个Worker线程,例如命名为“MyWorker”。 ![newWorker](figures/newWorker.png) -2. 在宿主线程中通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象。 +2. 在宿主线程中调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象。 ```ts // Index.ets @@ -88,8 +88,8 @@ struct Index { const workerInstance: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ets'); ``` -3. 在宿主线程中通过调用[onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9)方法接收Worker线程发送过来的消息,并通过调用[postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9)方法向Worker线程发送消息。 - 例如,向Worker线程发送训练和预测的消息,并接收Worker线程发送回来的消息。 +3. 在宿主线程中调用[onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9)接收Worker线程消息,调用[postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9)发送消息。 + 例如,向Worker线程发送训练、预测消息,并接收其返回的消息。 ```ts // Index.ets @@ -112,7 +112,7 @@ struct Index { workerInstance.postMessage({ 'type': 0 }); ``` -4. 在MyWorker.ets文件中绑定Worker对象,当前线程即为Worker线程。 +4. 在MyWorker.ets文件中绑定Worker对象,当前线程为Worker线程。 ```ts // MyWorker.ets @@ -121,8 +121,8 @@ struct Index { let workerPort: ThreadWorkerGlobalScope = worker.workerPort; ``` -5. 在Worker线程中通过调用[onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9-1)方法接收宿主线程发送的消息,并通过调用[postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9-2)方法向宿主线程发送消息。 - 例如,在Worker线程中定义预测模型及其训练过程,并与宿主线程进行信息交互。 +5. 在Worker线程中通过调用[onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9-1)方法接收主线程发送的消息,并通过调用[postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9-2)方法向主线程发送消息。 + 例如,在Worker线程中定义预测模型及其训练过程,并与宿主线程交互信息。 ```ts // MyWorker.ets @@ -159,7 +159,7 @@ struct Index { } ``` -6. 在Worker线程中完成任务之后,执行Worker线程销毁操作。销毁线程的方式主要有两种:根据需要可以在宿主线程中对Worker线程进行销毁;也可以在Worker线程中主动销毁Worker线程。 +6. 在Worker线程完成任务后,执行销毁操作。销毁线程的方式有两种:一是在宿主线程中销毁Worker线程,二是在Worker线程中主动销毁自身。 在宿主线程中通过调用[onexit()](../reference/apis-arkts/js-apis-worker.md#onexit9)方法定义Worker线程销毁后的处理逻辑。 @@ -171,7 +171,7 @@ struct Index { } ``` - 方式一:在宿主线程中通过调用[terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9)方法销毁Worker线程,并终止Worker接收消息。 + 方式一:在主线程中通过调用[terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9)方法销毁Worker线程,并终止Worker接收消息。 ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/global-configuration-guide.md b/zh-cn/application-dev/arkts-utils/global-configuration-guide.md index 116fffcb6a1..9c2e0acca84 100644 --- a/zh-cn/application-dev/arkts-utils/global-configuration-guide.md +++ b/zh-cn/application-dev/arkts-utils/global-configuration-guide.md @@ -1,8 +1,8 @@ # 全局配置项功能场景 -对于需要使用进程单例的场景,例如不同并发实例间需要数据保持一致的全局配置项业务,可以采用共享模块来实现。 +对于需要使用进程单例的场景,例如不同并发实例间需要保持数据一致的全局配置项,可以采用共享模块来实现。 -以下示例展示了只有在Wi-Fi打开且用户登录的情况下才能进行下载的业务功能,具体步骤如下。 +以下示例展示了在Wi-Fi开启且用户已登录的情况下才能执行下载操作的业务功能,具体步骤如下。 1. 编写全局配置文件。 @@ -15,40 +15,40 @@ @Sendable class Config { - lock: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock + lock: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock(); isLogin: boolean = false; loginUser?: string; - wifiOn: boolean = false + wifiOn: boolean = false; async login(user: string) { return this.lock.lockAsync(() => { this.isLogin = true; - this.loginUser = user + this.loginUser = user; }, ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE) } async logout(user?: string) { return this.lock.lockAsync(() => { - this.isLogin = false + this.isLogin = false; this.loginUser = "" }, ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE) } async getIsLogin(): Promise { return this.lock.lockAsync(() => { - return this.isLogin + return this.isLogin; }, ArkTSUtils.locks.AsyncLockMode.SHARED) } async getUser(): Promise { return this.lock.lockAsync(() => { - return this.loginUser! + return this.loginUser!; }, ArkTSUtils.locks.AsyncLockMode.SHARED) } async setWifiState(state: boolean) { return this.lock.lockAsync(() => { - this.wifiOn = state + this.wifiOn = state; }, ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE) } @@ -62,7 +62,7 @@ export let config = new Config() ``` -2. UI主线程及子线程访问全局配置项。 +2. UI主线程和子线程访问全局配置项。 ```ts import { config } from './Config' @@ -120,7 +120,7 @@ .onClick(async () => { if (!await config.getIsLogin() && this.input) { this.message = "login: " + this.input - config.login(this.input) + config.login(this.input); } }) .backgroundColor(0xcccccc) @@ -134,7 +134,7 @@ .onClick(async () => { if (await config.getIsLogin()) { this.message = "not login" - config.logout() + config.logout(); } }) .backgroundColor(0xcccccc) @@ -158,7 +158,7 @@ middle: { anchor: '__container__', align: HorizontalAlign.Center } }) .onClick(async () => { - let ret = await taskpool.execute(download) + let ret = await taskpool.execute(download); this.downloadResult = ret ? "download success" : "download fail"; }) Text(this.downloadResult) diff --git a/zh-cn/application-dev/arkts-utils/independent-time-consuming-task.md b/zh-cn/application-dev/arkts-utils/independent-time-consuming-task.md index 265e0de2416..be12b3bb8d6 100644 --- a/zh-cn/application-dev/arkts-utils/independent-time-consuming-task.md +++ b/zh-cn/application-dev/arkts-utils/independent-time-consuming-task.md @@ -1,10 +1,10 @@ # 使用TaskPool执行独立的耗时任务 -对于独立运行的耗时任务,任务执行完毕后将结果返回给宿主线程,没有上下文依赖,可采用以下方式实现。 +对于独立运行的耗时任务,任务完成后返回结果给宿主线程。可采用以下方式实现。 -下面通过图片加载来说明。 +下面通过图片加载说明。 -1. 实现子线程需要执行的任务。 +1. 实现子线程任务。 ```ts // IconItemSource.ets @@ -23,7 +23,7 @@ // IndependentTask.ets import { IconItemSource } from './IconItemSource'; - // 在Task中执行的方法,需要添加@Concurrent注解,否则无法正常调用。 + //在Task中执行的方法需要添加@Concurrent注解。 @Concurrent export function loadPicture(count: number): IconItemSource[] { let iconItemSourceList: IconItemSource[] = []; @@ -42,7 +42,7 @@ } ``` -2. 使用TaskPool中的execute方法执行上述任务,加载图片。 +2. 使用TaskPool的execute方法执行任务,加载图片。 ```ts // Index.ets @@ -65,7 +65,7 @@ let iconItemSourceList: IconItemSource[] = []; // 创建Task let loadPictureTask: taskpool.Task = new taskpool.Task(loadPicture, 30); - // 执行Task,并返回结果 + // 执行Task并返回结果 taskpool.execute(loadPictureTask).then((res: object) => { // loadPicture方法的执行结果 iconItemSourceList = res as IconItemSource[]; diff --git a/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md b/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md index 80b71d478af..202664d5687 100644 --- a/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md +++ b/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md @@ -1,18 +1,18 @@ # ArkTS线程间通信概述 -线程间通信指的是并发多线程间存在的数据交换行为。由于ArkTS语言兼容TS/JS,其运行时的实现与其它所有的JS引擎一样,都是基于Actor内存隔离的并发模型提供并发能力。 +线程间通信指并发多线程间的数据交换。由于ArkTS兼容TS/JS,其运行时实现与所有JS引擎相同,基于Actor内存隔离的并发模型提供并发能力。 -在ArkTS线程间通信中,不同数据对象的行为存在差异。例如,普通JS对象、ArrayBuffer对象和SharedArrayBuffer对象在跨线程时的行为不一致,包括序列化和反序列化、数据转移和数据共享等操作。 +在ArkTS线程间通信中,不同数据对象的行为有差异。普通JS对象、ArrayBuffer对象和SharedArrayBuffer对象在跨线程时的序列化、反序列化、数据转移和数据共享操作各不相同。 -以JS对象为例,其在并发任务间的通信采用了标准的Structured Clone算法(序列化和反序列化)。该算法通过序列化将JS对象转换为与引擎无关的数据(如字符串或内存块),在另一个并发实例中通过反序列化还原成与原JS对象内容一致的新对象。因此,需要进行深拷贝,效率较低。除了支持JS标准的序列化和反序列化能力,还支持绑定Native的JS对象的传输,以及[Sendable对象](arkts-sendable.md)的共享能力。 +以JS对象为例,其在并发任务间的通信使用了标准的Structured Clone算法(序列化和反序列化)。该算法通过序列化将JS对象转换为与引擎无关的数据(如字符串或内存块),在另一个并发实例中通过反序列化还原成内容一致的新对象。因此,需要进行深拷贝,效率较低。此外,还支持绑定Native的JS对象传输和[Sendable对象](arkts-sendable.md)的共享。 -ArkTS目前主要提供两种并发能力支持线程间通信:TaskPool和Worker。 +ArkTS提供两种并发能力支持线程间通信:TaskPool和Worker。 -- Worker是Actor并发模型标准的跨线程通信API,与Web Worker或者Node.js Worker的使用方式基本一致。 +- Worker是Actor并发模型标准的跨线程通信API,与Web Worker或Node.js Worker的使用方式一致。 -- TaskPool提供了功能更强、并发编程更简易的任务池API。其中TaskPool涉及跨并发实例的对象传递行为与Worker一致,还是采用了标准的Structured Clone算法,并发通信的对象越大,耗时就越长。 +TaskPool提供强大的任务池API,简化并发编程。TaskPool在跨并发实例传递对象时,与Worker一样使用标准的Structured Clone算法。对象越大,通信耗时越长。 -基于ArkTS提供的TaskPool和Worker并发接口,支持多种线程间通信能力,可以满足开发者的不同[线程间通信场景](independent-time-consuming-task.md)。如独立的耗时任务、多个耗时任务、TaskPool线程与宿主线程通信、Worker线程与宿主线程的异步通信、Worker同步调用宿主线程的接口等。同时,基于[Node-API](../napi/napi-introduction.md)提供的机制,C++线程可以跨线程调用ArkTS接口。 +基于ArkTS提供的TaskPool和Worker并发接口,支持多种线程间通信能力,满足开发者的不同线程间通信需求。这些场景包括独立的耗时任务、多个耗时任务、TaskPool线程与宿主线程通信、Worker线程与宿主线程的异步通信、Worker同步调用宿主线程的接口等。此外,基于Node-API提供的机制,C++线程可以跨线程调用ArkTS接口。 图1 序列化反序列化原理图 diff --git a/zh-cn/application-dev/arkts-utils/io-intensive-task-development.md b/zh-cn/application-dev/arkts-utils/io-intensive-task-development.md index c148bd6e424..39cfcd2e28e 100644 --- a/zh-cn/application-dev/arkts-utils/io-intensive-task-development.md +++ b/zh-cn/application-dev/arkts-utils/io-intensive-task-development.md @@ -1,13 +1,13 @@ # I/O密集型任务开发指导 (TaskPool) -使用异步并发可以解决单次I/O任务阻塞的问题,但如果遇到I/O密集型任务,同样会阻塞线程中其它任务的执行,这时需要使用多线程并发能力来进行解决。 +使用异步并发可以解决单次I/O任务阻塞的问题。对于I/O密集型任务,若要避免阻塞其他任务的执行,则需采用多线程并发。 -I/O密集型任务的性能关键在于I/O操作的速度和效率,而非CPU的处理能力。这类任务需要频繁进行磁盘读写和网络通信。此处通过频繁读写系统文件来模拟I/O密集型并发任务的处理。 +I/O密集型任务的性能取决于I/O操作的速度和效率。这类任务需要频繁进行磁盘读写和网络通信。通过频繁读写系统文件来模拟I/O密集型并发任务。 -1. 定义并发函数,内部密集调用I/O能力。 +1. 定义并发函数,内部频繁调用I/O能力。 ```ts // write.ets import { fileIo } from '@kit.CoreFileKit' @@ -35,12 +35,12 @@ I/O密集型任务的性能关键在于I/O操作的速度和效率,而非CPU // 循环写文件操作 let fileList: Array = []; fileList.push(filePath1); - fileList.push(filePath2) + fileList.push(filePath2); for (let i: number = 0; i < fileList.length; i++) { write('Hello World!', fileList[i]).then(() => { console.info(`Succeeded in writing the file. FileList: ${fileList[i]}`); }).catch((err: BusinessError) => { - console.error(`Failed to write the file. Code is ${err.code}, message is ${err.message}`) + console.error(`Failed to write the file. Code is ${err.code}, message is ${err.message}`); return false; }) } @@ -48,7 +48,7 @@ I/O密集型任务的性能关键在于I/O操作的速度和效率,而非CPU } ``` -2. 使用TaskPool执行包含密集I/O的并发函数,通过调用[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute)方法执行任务,并在回调中处理调度结果。示例中获取filePath1和filePath2的方式请参见[获取应用文件路径](../application-models/application-context-stage.md#获取应用文件路径)。在TaskPool中使用context时,需先在并发函数外部准备好,并通过参数传递给并发函数。 +2. 使用TaskPool执行包含密集I/O的并发函数,通过调用`execute()`方法执行任务,并在回调中处理调度结果。示例中获取`filePath1`和`filePath2`的方式请参见[获取应用文件路径](../application-models/application-context-stage.md#获取应用文件路径)。在TaskPool中使用context时,需先在并发函数外部准备好,并通过参数传递给并发函数。 ```ts // Index.ets @@ -66,7 +66,7 @@ I/O密集型任务的性能关键在于I/O操作的速度和效率,而非CPU let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // 使用TaskPool执行包含密集I/O的并发函数 - // 数组较大时,I/O密集型任务分发也会抢占UI主线程,需要使用多线程能力 + // 当数组大小超过特定阈值时,I/O密集型任务分发可能会抢占UI主线程,需要使用多线程处理。 taskpool.execute(concurrentTest, context).then(() => { // 调度结果处理 console.info("taskpool: execute success") diff --git a/zh-cn/application-dev/arkts-utils/long-time-task-guide.md b/zh-cn/application-dev/arkts-utils/long-time-task-guide.md index caf50334ab4..bcef5a623ba 100644 --- a/zh-cn/application-dev/arkts-utils/long-time-task-guide.md +++ b/zh-cn/application-dev/arkts-utils/long-time-task-guide.md @@ -1,6 +1,6 @@ # 长时任务开发指导(TaskPool) -此处提供使用TaskPool进行长时任务的开发指导,以定期采集传感器数据为例。 +提供使用TaskPool进行长时任务开发的指导,以定期采集传感器数据为例。 ## 使用TaskPool进行传感器数据监听 @@ -13,7 +13,7 @@ import { BusinessError, emitter } from '@kit.BasicServicesKit'; ``` -2. 定义长时任务,内部监听sensor数据,并通过emitter注册销毁通知。 +2. 定义长时任务,监听传感器数据并注册销毁通知。 ```ts // Index.ets @@ -30,9 +30,9 @@ } ``` -3. 宿主线程定义注册及销毁的行为。 - - 注册:发起长时任务,并通过emitter接收监听数据。 - - 销毁:发送取消传感器监听的事件,并结束长时任务。 +3. 宿主线程定义注册和删除行为。 + - 注册:发起长时任务并接收监听数据。 + - 删除:取消传感器监听并结束长时任务。 ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/long-time-task-overview.md b/zh-cn/application-dev/arkts-utils/long-time-task-overview.md index 301fff4f2a6..ff217d3e90d 100644 --- a/zh-cn/application-dev/arkts-utils/long-time-task-overview.md +++ b/zh-cn/application-dev/arkts-utils/long-time-task-overview.md @@ -1,13 +1,13 @@ # 长时任务并发场景简介 -在应用业务实现过程中,对于需要较长时间不定时运行的任务,称为长时任务。如果在UI主线程中执行这些长时任务,会阻塞UI主线程的UI业务,导致卡顿和丢帧等问题,影响用户体验。因此,通常需要将这些独立的长时任务放到单独的子线程中执行。 +在应用业务实现过程中,需要长时间运行的任务称为长时任务。如果在UI主线程中执行长时任务,会阻塞UI业务,导致卡顿和丢帧,影响用户体验。因此,应将这些独立的长时任务放到单独的子线程中执行。 典型的长时任务场景如下所示: | 常见业务场景 | 具体业务描述 | | -------- | -------- | -| 定期采集传感器数据 | 周期性采集一些传感器信息(例如位置信息、速度传感器等),应用需要长时间不间断的运行。 | +| 定期采集传感器数据 | 周期性采集传感器信息,应用需要长时间运行。 | | 监听Socket端口信息 | 长时间监听Socket数据,不定时需要响应处理。 | -上述业务场景均为独立的长时任务,任务执行周期长,与外部交互简单。分发到后台线程后,这些任务需要不定期响应以获取结果。这些类型的任务使用TaskPool可以简化开发工作量,避免管理复杂的生命周期,避免线程泛滥。开发者只需要将上述独立的长时任务放入TaskPool队列,再等待结果即可。 +上述业务场景为独立的长时任务,执行周期长,与外部交互简单。分发到后台线程后,这些任务需要定期响应以获取结果。使用TaskPool可以简化开发工作量,避免管理复杂的生命周期和线程泛滥。开发者只需将这些独立的长时任务放入TaskPool队列,等待结果即可。 diff --git a/zh-cn/application-dev/arkts-utils/makeobserved-sendable.md b/zh-cn/application-dev/arkts-utils/makeobserved-sendable.md index 05edbcf5074..f117f862328 100644 --- a/zh-cn/application-dev/arkts-utils/makeobserved-sendable.md +++ b/zh-cn/application-dev/arkts-utils/makeobserved-sendable.md @@ -1,12 +1,12 @@ # ArkUI数据更新场景 -当需要网络下载或者本地生成的数据需要发送到UI线程进行展示时,由于ArkUI的标注和[\@Sendable装饰器](../arkts-utils/arkts-sendable.md#sendable装饰器)不能同时修饰变量和对象,因此需要使用[makeObserved](../ui/state-management/arkts-new-makeObserved.md)在ArkUI中导入可观察的Sendable共享数据。 +当需要将网络下载或本地生成的数据发送到UI线程进行展示时,由于ArkUI的装饰器和`@Sendable`装饰器不能同时修饰变量和对象,因此需要使用`makeObserved`在ArkUI中导入可观察的Sendable共享数据。 本示例说明以下场景: -- makeObserved在传入@Sendable类型的数据后有观察能力,且其变化可以触发UI刷新。 -- 从子线程获取数据,然后整体替换UI线程的可观察数据。 -- 从子线程获取的数据重新执行makeObserved,将数据变为可观察数据。 -- 将数据从UI主线程传递回子线程时,只传递不可观察的数据。makeObserved的返回值不能直接传给子线程。 +- `makeObserved` 传入 `@Sendable` 类型的数据后,具有观察能力,并且数据变化可触发 UI 刷新。 +- 从子线程获取数据,替换UI线程的可观察数据。 +- 从子线程获取的数据重新执行makeObserved,变为可观察的Sendable共享数据。 +- 将数据从UI主线程传递回子线程时,只传递不可观察的Sendable共享数据。makeObserved的返回值不能传给子线程。 ```ts // SendableData.ets diff --git a/zh-cn/application-dev/arkts-utils/multi-thread-cancel-task.md b/zh-cn/application-dev/arkts-utils/multi-thread-cancel-task.md index bfae47e9db6..dd7cd313bd6 100644 --- a/zh-cn/application-dev/arkts-utils/multi-thread-cancel-task.md +++ b/zh-cn/application-dev/arkts-utils/multi-thread-cancel-task.md @@ -1,8 +1,8 @@ # 多线程取消TaskPool任务场景 -由于任务池[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)的任务对象[Task](../reference/apis-arkts/js-apis-taskpool.md#task)不支持跨线程传递,因此无法在子线程中取消任务。从 API version 18 开始,Task新增了[任务ID](../reference/apis-arkts/js-apis-taskpool.md#属性)属性,支持通过任务ID在子线程中取消任务。以下示例提供多线程取消已提交给TaskPool中的任务开发指导,开发者可将已创建任务的任务ID存储在[Sendable对象](./arkts-sendable.md)中,需要取消任务时,通过Sendable对象来多线程取消任务。 +任务池 `TaskPool` 的任务对象 `Task` 不支持跨线程传递,因此无法在子线程中直接取消任务。从 API version 18 开始,`Task` 新增了任务ID属性,支持通过任务ID在子线程中取消任务。以下示例提供多线程取消已提交给 `TaskPool` 的任务的开发指导。将已创建任务的任务ID存储在 `Sendable` 对象中,需要取消任务时,通过 `Sendable` 对象来多线程取消任务。 -1. 定义一个Sendable类,在类属性中存储任务ID。 +1. 定义Sendable类,类属性存储任务ID。 ```ts // Mock.ets @@ -22,7 +22,7 @@ } ``` -2. 在UI主线程向TaskPool提交一个延时任务,并在子线程取消该任务。 +2. 在UI主线程提交一个延时任务到TaskPool,并在子线程取消该任务。 ```ts // Index.ets @@ -55,9 +55,9 @@ .padding(10) .fontWeight(FontWeight.Bold) .onClick(async () => { - let task = new taskpool.Task(delayed); - taskpool.executeDelayed(2000, task); - let send = new SendableTest(task.taskId); + let task = new taskpool.Task(delayed); // 创建任务并获取任务ID + taskpool.executeDelayed(2000, task); // 提交任务并获取任务ID + let send = new SendableTest(task.taskId); // 将任务ID存储在Sendable对象中 taskpool.execute(cancel, send); }) } diff --git a/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md b/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md index eb32a6bf4f2..a8e83074dd6 100644 --- a/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md @@ -1,19 +1,19 @@ # 多线程并发概述 -多线程并发是指​​在单个程序中同时运行多个线程,通过并行或交替执行任务来提升性能和资源利用率​​的编程模型。在ArkTS应用开发过程中,需要用到多线程并发的业务场景有很多,针对常见的业务场景,主要可以分为以下三类,更详细的使用请参考[多线程开发实践案例](batch-database-operations-guide.md)。 +多线程并发是指在单个程序中同时运行多个线程,通过并行或交替执行任务来提升性能和资源利用率的编程模型。在ArkTS应用开发过程中,需要用到多线程并发的业务场景有很多,针对常见的业务场景,主要可以分为以下三类,更详细的使用请参考[多线程开发实践案例](batch-database-operations-guide.md)。 -- 业务逻辑包含较大计算量或多次I/O读写等需要长时间执行的任务,例如图片/视频编解码,压缩/解压缩,数据库操作等场景。 +- 业务逻辑包含高计算量或多次I/O读写等需要长时间执行的任务,例如图像/视频编解码,压缩/解压缩,数据库操作等场景。 - 业务逻辑包含监听或定期采集数据等需要长时间保持运行的任务,例如定期采集传感器数据场景。 -- 业务逻辑跟随主线程生命周期或与主线程绑定的任务,例如游戏中台场景。 +- 业务逻辑跟随主线程生命周期或与主线程绑定的任务,例如游戏平台场景。 并发模型用于实现不同应用场景中的并发任务。常见的并发模型有基于内存共享的模型和基于消息通信的模型。 Actor并发模型是基于消息通信的并发模型的典型代表。它使开发者无需处理锁带来的复杂问题,并且具有较高的并发度,因此得到了广泛的应用。 -当前ArkTS提供了TaskPool和Worker两种并发能力,两者均基于Actor并发模型实现。 +当前ArkTS提供了TaskPool和Worker两种并发能力,两者都基于Actor并发模型实现。 Actor并发模型和内存共享并发模型的具体对比请见[多线程并发模型](#多线程并发模型)。 @@ -23,9 +23,9 @@ Actor并发模型和内存共享并发模型的具体对比请见[多线程并 Actor并发模型每一个线程都是一个独立Actor,每个Actor有自己独立的内存,Actor之间通过消息传递机制触发对方Actor的行为,不同Actor之间不能直接访问对方的内存空间。 -Actor并发模型相较于内存共享并发模型,不同线程间的内存是隔离的,因此不会出现线程竞争同一内存资源的情况。开发者无需处理内存上锁相关的问题,从而提高开发效率。 +Actor并发模型中,不同线程间的内存隔离,不会竞争同一内存资源。开发者无需处理内存上锁问题,提高开发效率。 -Actor并发模型中,线程不共享内存,需通过线程间通信机制传递任务和结果。 +在Actor并发模型中,线程不共享内存,需要通过线程间通信机制传递任务和结果。 本文以经典的生产者消费者问题为例,对比呈现这两种模型在解决具体问题时的差异。 @@ -35,7 +35,7 @@ Actor并发模型中,线程不共享内存,需通过线程间通信机制传 ![zh-cn_image_0000002001497485](figures/zh-cn_image_0000002001497485.png) -为了避免不同生产者或消费者同时访问一块共享内存的容器时产生的脏读、脏写现象,同一时间只能有一个生产者或消费者访问该容器,也就是不同生产者和消费者争夺使用容器的锁。当一个角色获取锁之后其他角色需要等待该角色释放锁之后才能重新尝试获取锁以访问该容器。 +为了避免脏读、脏写,同一时间只能有一个生产者或消费者访问容器。当一个角色获取锁后,其他角色需等待锁释放后才能访问容器。 ```ts // 此段示例为伪代码仅作为逻辑示意,便于开发者理解使用内存共享模型和Actor模型的区别 @@ -195,7 +195,7 @@ struct Index { } ``` -也可以等待生产者完成所有生产任务,通过序列化通信将结果发送给UI线程。UI线程接收完毕后,由消费者统一消费结果。 +等待生产者完成所有生产任务,通过序列化通信将结果发送给UI线程。UI线程接收完毕后,消费者统一消费结果。 ```ts import { taskpool } from '@kit.ArkTS'; diff --git a/zh-cn/application-dev/arkts-utils/multi-time-consuming-tasks.md b/zh-cn/application-dev/arkts-utils/multi-time-consuming-tasks.md index c1b9ebdfa2f..e903a4ce423 100644 --- a/zh-cn/application-dev/arkts-utils/multi-time-consuming-tasks.md +++ b/zh-cn/application-dev/arkts-utils/multi-time-consuming-tasks.md @@ -1,12 +1,12 @@ # 使用TaskPool执行多个耗时任务 -多个任务同时执行时,由于任务复杂度不同,执行时间和返回数据的时间也会不同。如果宿主线程需要所有任务执行完毕的数据,可以通过[TaskGroup](../reference/apis-arkts/js-apis-taskpool.md#taskgroup10)的方式实现。 +多个任务同时执行时,由于任务复杂度不同,执行时间和返回数据的时间会有所差异。如果宿主线程需要所有任务完成后的数据,可以使用[TaskGroup](../reference/apis-arkts/js-apis-taskpool.md#taskgroup10)实现。 -除此以外,如果需要处理的数据量较大,例如一个列表中有10000条数据,将这些数据放在一个Task中处理会非常耗时。那么就可以将原始数据拆分成多个子列表,为每个子列表分配一个独立的Task执行,等待全部Task执行完成后合并结果形成完整的数据,这样可以节省处理时间,提升用户体验。 +除了上述情况,处理大量数据时,例如列表包含10000条记录,应将数据拆分为多个子列表,每个子列表分配一个独立的Task处理。待所有Task完成后,合并结果以形成完整数据,从而节省处理时间,提高用户体验。 下面以多个任务进行图片加载为例进行说明。 -1. 实现子线程需要执行的任务。 +1. 实现子线程需要执行的Task。 ```ts // IconItemSource.ets @@ -45,7 +45,7 @@ } ``` -2. 将需要执行的Task放到了一个TaskGroup里面,当TaskGroup中的所有Task执行完毕后,会将每个Task的结果都放在一个数组中并返回给宿主线程,而不是每执行完一个Task就返回一次,这样宿主线程就可以在返回的数据里拿到所有Task的执行结果,便于后续使用。 +2. 将需要执行的任务放入TaskGroup中。当TaskGroup中的所有任务执行完毕后,会将每个任务的结果收集到一个数组中并返回给宿主线程。这样,宿主线程可以在返回的数据中获取所有任务的执行结果,便于后续使用。 ```ts // MultiTask.ets @@ -60,7 +60,7 @@ taskGroup.addTask(new taskpool.Task(loadPicture, 20)); taskGroup.addTask(new taskpool.Task(loadPicture, 10)); taskpool.execute(taskGroup).then((ret: object) => { - let tmpLength = (ret as IconItemSource[][]).length + let tmpLength = (ret as IconItemSource[][]).length; for (let i = 0; i < tmpLength; i++) { for (let j = 0; j < ret[i].length; j++) { iconItemSourceList.push(ret[i][j]); diff --git a/zh-cn/application-dev/arkts-utils/multithread-develop-overview.md b/zh-cn/application-dev/arkts-utils/multithread-develop-overview.md index 4177c102d2d..2cde44e0452 100644 --- a/zh-cn/application-dev/arkts-utils/multithread-develop-overview.md +++ b/zh-cn/application-dev/arkts-utils/multithread-develop-overview.md @@ -1,15 +1,15 @@ # 应用多线程开发概述 -在ArkTS应用开发过程中,不同的业务场景需要使用不同的并发能力,对应的主要任务类型也各不相同。 +ArkTS应用开发中,不同业务场景需要不同的并发能力,对应不同的任务类型。 -常见的业务场景分为三种并发任务: +业务场景分为三种并发任务: -[耗时任务](time-consuming-task-overview.md):业务逻辑包含较大计算量或多次I/O读写等需要长时间执行的任务。 +[耗时任务](time-consuming-task-overview.md):业务逻辑包含计算量超过100万次操作或多次I/O读写等需要执行超过10秒的任务。 -[长时任务](long-time-task-overview.md):业务逻辑包含监听或定期采集数据等需要长时间保持运行的任务。 +[长时任务](long-time-task-overview.md):业务逻辑包含监听或定期采集数据等需要持续运行超过1小时的任务。 [常驻任务](resident-task-overview.md):业务逻辑跟随主线程生命周期或与主线程绑定的任务。 -不同任务类型可以进一步细分。例如,典型的耗时任务包括CPU密集型任务、I/O密集型任务和同步任务,每种任务类型对应不同的业务场景。请根据具体场景选择合适的并发能力。 +任务类型可以进一步细分,例如,耗时任务包括CPU密集型、I/O密集型和同步任务。根据具体场景选择合适的并发能力。 接下来的章节将列举多线程开发中常见的场景及其案例。 diff --git a/zh-cn/application-dev/arkts-utils/native-interthread-shared.md b/zh-cn/application-dev/arkts-utils/native-interthread-shared.md index 5ad3eb1eff3..d4e5fb85f24 100644 --- a/zh-cn/application-dev/arkts-utils/native-interthread-shared.md +++ b/zh-cn/application-dev/arkts-utils/native-interthread-shared.md @@ -1,15 +1,15 @@ # C++线程间数据共享场景 -当应用在C++层进行多线程并发计算时,因为ArkTS的API需要在ArkTS环境中执行,为了避免在非UI主线程每次回调时等待UI主线程的API调用结果,需要在这些C++线程上创建ArkTS执行环境并直接调用API。此外,可能需要在C++线程之间共享和操作Sendable对象。 +当应用在C++层进行多线程并发计算时,因为ArkTS的API需要在ArkTS环境中执行,为了避免在非UI主线程每次回调时等待UI主线程的API调用结果,应在这些C++线程上创建ArkTS执行环境并直接调用API。此外,需要在C++线程之间共享和操作Sendable对象。 -为了支持此类场景,C++线程需具备创建调用ArkTS的能力,并对Sendable对象进行多线程共享和操作。 +为了支持此类场景,C++线程需要创建调用ArkTS,并多线程共享和操作Sendable对象。 ## 在C++线程上调用ArkTS能力 -关于如何使用Node-API接口在C++线程创建ArkTS运行环境并调用,开发者可以参考[使用Node-API接口创建ArkTS运行时环境](../napi/use-napi-ark-runtime.md)。 +开发者可以参考[使用Node-API接口创建ArkTS运行时环境](../napi/use-napi-ark-runtime.md),了解如何在C++线程中创建ArkTS运行环境并调用Node-API接口。 -核心代码片段如下所示: +核心代码片段如下: ArkTS文件定义。 @@ -24,7 +24,7 @@ export class SendableObjTest { ``` -实现Native加载ArkTS模块的能力。 +实现Native加载ArkTS模块。 ```cpp // napi_init.cpp @@ -73,13 +73,13 @@ static void *CreateArkRuntimeFunc(void *arg) } ``` -主要步骤包括:创建执行环境、加载模块、查找并调用模块函数(也可以直接通过Node-API接口创建Sendable对象),最后销毁执行环境。关于第二步加载模块的详细信息,请参见[使用Node-API接口进行模块加载](../napi/use-napi-load-module-with-info.md)。关于第三步查找并调用函数及更多Node-API接口能力,请参见[Node-API](../reference/native-lib/napi.md#node-api)。 +主要步骤包括:创建执行环境、加载模块、查找并调用模块函数(或直接通过Node-API接口创建Sendable对象),最后销毁执行环境。关于加载模块的详细信息,请参见[使用Node-API接口进行模块加载](../napi/use-napi-load-module-with-info.md)。关于查找并调用函数及更多Node-API接口能力,请参见[Node-API](../reference/native-lib/napi.md#node-api)。 ## 在C++线程之间操作Sendable共享对象 -实现在C++调用ArkTS能力后,需要通过序列化和反序列化跨线程传递。napi_value不是多线程安全的,不能直接在多线程之间共享。 +在C++中调用ArkTS能力后,需要通过序列化和反序列化实现跨线程传递。napi_value不是多线程安全的,不能在多线程间直接共享。 -下面代码例子说明了如何序列化和反序列化传递对象,注意因为Sendable共享对象是引用传递,所以序列化不会产生另外一份拷贝数据,而是直接传递对象引用到反序列化线程,所以在性能上相比非Sendable对象的序列化和反序列化更为高效。 +下面的代码示例展示了如何序列化和反序列化传递对象。注意,由于 `Sendable` 共享对象是通过引用传递的,因此序列化不会生成额外的数据拷贝,而是直接将对象引用传递到反序列化线程。这使得 `Sendable` 对象的序列化和反序列化在性能上优于非 `Sendable` 对象。 ArkTS文件定义。 @@ -246,9 +246,9 @@ struct Index { 整个过程主要包括的逻辑实现为: -1. 在入口main函数所在的UI主线程中创建ArkTS运行环境,并发起一个C++子线程创建Sendable对象,保存到result中,然后将result引用的Sendable对象序列化到全局序列化数据serializationData中。 +1. 在入口main函数的UI主线程中创建ArkTS运行环境,发起一个C++子线程创建Sendable对象并保存到result中,然后将result引用的Sendable对象序列化到全局序列化数据serializationData中。 -2. 当这些流程完成后,发起另外一个C++子线程,并在这个新的线程中创建ArkTS运行环境。然后再通过反序列化接口从serializationData中反序列化出UI主线程创建的Sendable对象,并保存到result中,从而实现了Sendable对象的跨C++线程传递。反序列化完成后,需要销毁反序列化数据避免内存泄露。这时UI主线程和子线程都同时持有这个Sendable共享对象,即可通过Node-API进行对象操作,比如读写或者传递到ArkTS层等。 +2. 当流程完成后,发起C++子线程,在新线程中创建ArkTS运行环境。通过反序列化接口从serializationData中反序列化出UI主线程创建的Sendable对象,并保存到result中,实现Sendable对象的跨C++线程传递。反序列化完成后,销毁反序列化数据以避免内存泄露。此时,UI主线程和子线程都持有Sendable共享对象,可通过Node-API进行对象操作,如读写或传递到ArkTS层。 > **说明:** > diff --git a/zh-cn/application-dev/arkts-utils/normal-object.md b/zh-cn/application-dev/arkts-utils/normal-object.md index 7dccffa9c7a..c86e3ff8e46 100644 --- a/zh-cn/application-dev/arkts-utils/normal-object.md +++ b/zh-cn/application-dev/arkts-utils/normal-object.md @@ -1,12 +1,12 @@ # 普通对象 -普通对象跨线程时通过拷贝形式传递,两个线程的对象内容一致,但是指向各自线程的隔离内存区间,被分配在各自线程的虚拟机本地堆(LocalHeap)。例如,Ecmascript262规范定义的Object、Array、Map等对象通过这种方式实现跨并发实例通信。通信过程如图所示: +普通对象跨线程时通过拷贝形式传递,两个线程的对象内容一致,但指向各自线程的隔离内存区间,被分配在各自线程的虚拟机本地堆(LocalHeap)。例如,ECMAScript 262 规范定义的Object、Array、Map等对象通过这种方式实现跨并发实例通信。通信过程如图所示。 ![deep_copy](figures/deep_copy.png) > **说明:** > -> 普通类实例对象跨线程通过拷贝形式传递,只能传递数据,类实例上的方法会丢失。可以使用[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标识为Sendable类,类实例对象跨线程传递后,可携带类方法。 +> 普通对象跨线程通过拷贝形式传递,只能传递数据,类实例上的方法会丢失。可以使用 `@Sendable` 装饰器标识为可发送类,类实例对象跨线程传递后,可携带类方法。 ## 使用示例 diff --git a/zh-cn/application-dev/arkts-utils/resident-task-guide.md b/zh-cn/application-dev/arkts-utils/resident-task-guide.md index 82d58b3b078..8e86ac19994 100644 --- a/zh-cn/application-dev/arkts-utils/resident-task-guide.md +++ b/zh-cn/application-dev/arkts-utils/resident-task-guide.md @@ -1,28 +1,28 @@ # 常驻任务开发指导(Worker) -提供使用Worker进行常驻任务的开发指导。Worker将持续执行任务,直到宿主线程发送终止指令。 +提供使用Worker进行常驻任务开发的指导。Worker将一直执行任务,直到宿主线程发送终止指令。 开发过程和示例如下: -1. DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,点击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息。本文以创建“Worker”为例。 +1. DevEco Studio支持一键生成Worker。在{moduleName}目录下的任意位置,点击鼠标右键,选择New > Worker,即可自动生成Worker的模板文件及配置信息。本文以创建Worker为例。 - 此外,还支持手动创建Worker文件,具体方式和相关注意事项请参见[创建Worker的注意事项](worker-introduction.md#创建worker的注意事项)。 + 此外,还支持手动创建Worker文件。具体方式和相关注意事项请参见[创建Worker的注意事项](worker-introduction.md#创建worker的注意事项)。 -2. 导入Worker模块。 +2. 在项目中导入Worker模块。 ```ts // Index.ets import { worker } from '@kit.ArkTS'; ``` -3. 在宿主线程中通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,当前线程为宿主线程。 +3. 在宿主线程中通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,宿主线程为宿主线程。 ```ts // Index.ets const workerInstance: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/Worker.ets'); ``` -4. 此处的宿主线程为UI主线程,宿主线程发送'start'以开始执行某个长期运行的任务,并接收子线程返回的相关消息。当不需要执行该任务时,发送'stop'以停止该任务的执行。在此示例中,任务将在10秒后结束。 +4. 在UI主线程中,发送'start'消息以启动长期运行的任务,并接收子线程返回的消息。当不再需要执行任务时,发送'stop'消息以停止任务。在此示例中,任务将在10秒后停止。 ```ts // Index.ets @@ -53,7 +53,7 @@ } ``` -5. 在Worker线程中,当接收到宿主线程发送的消息为'start'时,开始执行某个长时间不定期运行的任务,并实时向宿主线程返回消息。当接收到的消息为'stop'时,结束该任务的执行并返回相应的消息给宿主线程。 +5. 在Worker线程中,接收到宿主线程发送的'start'消息时,开始执行长时间任务,并实时向宿主线程返回消息。接收到'stop'消息时,结束任务执行并向宿主线程返回消息。 ```ts // Worker.ets diff --git a/zh-cn/application-dev/arkts-utils/resident-task-overview.md b/zh-cn/application-dev/arkts-utils/resident-task-overview.md index 3a908a82fa9..814386652f1 100644 --- a/zh-cn/application-dev/arkts-utils/resident-task-overview.md +++ b/zh-cn/application-dev/arkts-utils/resident-task-overview.md @@ -1,10 +1,10 @@ # 常驻任务并发场景简介 -在应用业务实现过程中,对于耗时较长(超过3分钟)且并发量不大的常驻任务场景,建议使用Worker在后台线程中执行这些耗时操作,从而避免阻塞UI主线程,防止出现丢帧、卡顿等影响用户体验的问题。 +在应用业务实现中,对于耗时超过3分钟且并发量小的常驻任务,建议使用Worker在后台线程执行这些操作,以避免阻塞UI主线程,防止丢帧和卡顿,提升用户体验。 -常驻任务是指相比于短时任务,时间更长的任务,可能跟UI主线程生命周期一致。相比于长时任务,常驻任务更倾向于跟线程绑定的任务,单次运行时间更长(比如超过3分钟)。 +常驻任务是与UI主线程生命周期一致的任务,单次运行时间通常超过3分钟。 -对应常驻任务,较为常见的业务场景如下: +对应常驻任务,常见的业务场景如下: | 常见业务场景 | 具体业务描述 | | -------- | -------- | diff --git a/zh-cn/application-dev/arkts-utils/sendable-constraints.md b/zh-cn/application-dev/arkts-utils/sendable-constraints.md index 9487d7609b2..9f54978e68c 100644 --- a/zh-cn/application-dev/arkts-utils/sendable-constraints.md +++ b/zh-cn/application-dev/arkts-utils/sendable-constraints.md @@ -4,7 +4,7 @@ ### Sendable类必须继承自Sendable类 -Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局。因此,不允许互相继承。这里的类不包括变量。Sendable类不能继承自变量。 +Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局。因此,不允许互相继承。这里的类不包括变量,Sendable类不能继承自变量。 **正例:** @@ -42,7 +42,7 @@ class B extends A { // A不是sendable class,B不能继承它,编译报错 ### 非Sendable类必须继承自非Sendable类 -Sendable对象的布局及原型链不可变,而非Sendable对象可以通过特殊方式修改布局,因此不允许互相继承。 +Sendable对象的布局和原型链不可变,而非Sendable对象可以特殊方式修改布局,因此禁止互相继承。 **正例:** @@ -79,7 +79,7 @@ class B extends A { // A是sendable class,B不能继承它,编译报错 ### 非Sendable类禁止实现Sendable接口 -如果非Sendable类实现Sendable接口,可能会被误认为是Sendable类,从而导致错误使用。 +非Sendable类实现Sendable接口时,可能被误认为是Sendable类,导致错误使用。 **正例:** @@ -105,7 +105,7 @@ class B implements I {}; // I是sendable interface,B不能实现,编译报 ### 必须是Sendable支持的数据类型 -Sendable数据不能持有非Sendable数据,因此Sendable类或接口的成员变量必须是Sendable支持的数据类型。 +Sendable数据不能持有非Sendable数据。因此成员变量必须是Sendable支持的数据类型。 **正例:** @@ -132,7 +132,7 @@ class A { ### 不支持使用!断言 -Sendable对象的成员属性必须赋初值,“!”修饰的变量可以不赋初值,因此不支持使用“!” 。 +Sendable对象的成员属性必须赋初值,不支持使用“!”修饰的变量。 **正例:** @@ -159,7 +159,7 @@ class A { ### 不支持使用计算属性名 -Sendable对象的布局不可变,计算属性无法静态确定对象布局,因此不支持。 +Sendable对象的布局不可变,计算属性无法静态确定,因此不支持。 **正例:** @@ -191,7 +191,7 @@ class A { ### 泛型类中的Sendable类、SendableLruCache、collections.Array、collections.Map和collections.Set的模板类型必须是Sendable类型 -Sendable数据不能持有非Sendable数据,因此泛型类中的Sendable数据的模版类型必须是Sendable类型。 +Sendable数据不能持有非Sendable数据,因此泛型类中的Sendable数据的模板类型必须是Sendable类型。 **正例:** @@ -227,7 +227,7 @@ try { ### Sendable类的内部不允许使用当前模块内上下文环境中定义的变量 -由于Sendable对象在不同并发实例间的上下文环境不同,属于单个虚拟机实例,如果直接访问会有非预期行为。不支持Sendable对象使用当前模块内上下文环境中定义的变量,违反此规则会在编译阶段报错。 +Sendable对象在不同并发实例间的上下文环境不同,属于单个虚拟机实例。直接访问会导致非预期行为。Sendable对象不支持使用当前模块内上下文环境中定义的变量,违反此规则会在编译阶段报错。 > **说明:** > @@ -328,7 +328,7 @@ type D = C; // 编译报错 ### Sendable类和Sendable函数禁止使用除\@Sendable外的装饰器 -如果在ts文件中定义类装饰器,可能会修改类的布局,从而导致运行时错误。 +在ts文件中定义类装饰器,可能导致运行时错误,因为类的布局会被修改。 **正例:** @@ -353,7 +353,7 @@ class C { ### 禁止使用对象字面量/数组字面量初始化Sendable对象 -对象字面量和数组字面量不是Sendable类型,Sendable数据类型必须通过Sendable类型的new表达式创建。 +对象字面量和数组字面量不是Sendable类型。Sendable类型必须通过Sendable类型的new表达式创建。 **正例:** @@ -377,7 +377,7 @@ let arr4: number[] = new collections.Array(1, 2, 3); // 编译报错 ### 禁止非Sendable类型强制转换为Sendable -除了Object类型,非Sendable类型不能强转成Sendable类型。非Sendable类型通过as强转成Sendable类型后,实际数据仍为非Sendable类型,会导致错误使用。Sendable类型在不违反Sendable规则的前提下,需要和非Sendable类型行为兼容,因此Sendable类型可以as强转成非Sendable类型。 +除了Object类型,非Sendable类型不能强转为Sendable类型。非Sendable类型通过as强转为Sendable类型后,实际数据仍为非Sendable类型,会导致错误使用。Sendable类型可以as强转为非Sendable类型,以保持与非Sendable类型的行为兼容。 **正例:** @@ -413,7 +413,7 @@ let a2: SendableA = new A() as SendableA; // 编译报错 ### 箭头函数不可标记为Sendable -箭头函数不支持\@Sendable装饰器,因此它是非Sendable函数,不支持共享。 +箭头函数不支持@Sendable装饰器。它是非Sendable函数,不支持共享。 **正例:** @@ -469,15 +469,15 @@ class SendableClass { | 规则 | | -------- | -| 禁止删除属性,不能使用的接口有:napi_delete_property。 | -| 禁止新增属性,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 | -| 禁止修改属性类型,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 | -| 不支持Symbol相关接口和类型,不能使用的接口有:napi_create_symbol、napi_is_symbol_object、napi_symbol。 | +| 禁止删除属性,不能使用的接口有:napi_delete_property。| +| 禁止新增属性,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。| +| 禁止修改属性类型,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。| +| 不支持Symbol相关接口和类型,不能使用的接口有:napi_create_symbol、napi_is_symbol_object、napi_symbol。| ## 与UI交互的规则 -Sendable数据需要与[makeObserved](../ui/state-management/arkts-new-makeObserved.md)联用,才可以观察Sendable对象的数据变化,具体使用请参考[makeObserved和@Sendable装饰的class配合文档](../ui/state-management/arkts-new-makeObserved.md#makeobserved和sendable装饰的class配合使用)。 +Sendable数据必须与`makeObserved`联用,才能观察Sendable对象的数据变化。具体使用请参考[makeObserved和@Sendable装饰的class配合文档](../ui/state-management/arkts-new-makeObserved.md#makeobserved和sendable装饰的class配合使用)。 ## 在HAR包中的使用规则 diff --git a/zh-cn/application-dev/arkts-utils/sendable-freeze.md b/zh-cn/application-dev/arkts-utils/sendable-freeze.md index 6abe3c0e3bc..603066f0670 100644 --- a/zh-cn/application-dev/arkts-utils/sendable-freeze.md +++ b/zh-cn/application-dev/arkts-utils/sendable-freeze.md @@ -1,14 +1,14 @@ # Sendable对象冻结 -Sendable对象支持冻结操作,冻结后的对象变成只读对象,不能增删改属性,因此在多个并发实例间访问均不需要加锁,可以通过调用[Object.freeze](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)接口冻结对象。 +Sendable对象支持冻结操作,冻结后变为只读,不能增删改属性。因此,在多个并发实例间访问时无需加锁,可调用`Object.freeze`接口冻结对象。 > **说明:** > -> 不支持在.ets文件中使用Object.freeze接口。 +> 不支持在.ets文件中使用Object.freeze方法。 ## 使用示例 -1. 提供ts文件封装Object.freeze方法。 +1. 封装Object.freeze方法。 ```ts // helper.ts @@ -17,7 +17,7 @@ Sendable对象支持冻结操作,冻结后的对象变成只读对象,不能 } ``` -2. 调用freeze方法冻结对象,然后将对象发送到子线程。 +2. 调用freeze方法冻结对象,将其发送到子线程。 ```ts // Index.ets @@ -55,7 +55,7 @@ Sendable对象支持冻结操作,冻结后的对象变成只读对象,不能 } ``` -3. 子线程不加锁直接操作对象。 +3. 子线程直接操作对象,不加锁。 ```ts // Worker.ets diff --git a/zh-cn/application-dev/arkts-utils/sendable-guide.md b/zh-cn/application-dev/arkts-utils/sendable-guide.md index 70b73667455..4767cf04e89 100644 --- a/zh-cn/application-dev/arkts-utils/sendable-guide.md +++ b/zh-cn/application-dev/arkts-utils/sendable-guide.md @@ -1,5 +1,5 @@ # Sendable使用场景 -Sendable对象在不同并发实例间默认的传递方式为引用传递,相比序列化方式更高效,同时不会丢失class上携带的成员方法。因此,Sendable可以解决两个关键场景的问题: +Sendable对象在不同并发实例间默认采用引用传递,比序列化方式更高效,且不会丢失类上的成员方法。因此,Sendable能够解决两个关键场景的问题: - 跨并发实例传输大数据(例如达到100KB以上的数据)。 @@ -7,7 +7,7 @@ Sendable对象在不同并发实例间默认的传递方式为引用传递,相 ## 跨并发实例传输大数据场景 -由于跨并发实例序列化的开销随数据量线性增长,因此当传输数据量较大时(100KB的数据传输耗时约为1ms),跨并发实例的拷贝开销会影响应用性能。使用引用传递方式传输对象可提升性能。 +跨并发实例序列化的开销随数据量线性增长,100KB数据传输耗时约为1ms。因此,大容量数据传输时,跨并发实例的拷贝开销会影响应用性能。使用引用传递方式传输对象可以提升性能。 **示例:** @@ -106,7 +106,7 @@ export class Test { ## 跨并发实例传递带方法的class实例对象 -由于序列化传输实例对象时会丢失方法,因此在需要调用实例方法时,需使用引用传递方式。在数据处理过程中有需要解析的数据,可使用[ASON工具](ason-parsing-generation.md)解析。 +序列化传输实例对象时会丢失方法,因此在需要调用实例方法时,使用引用传递方式。数据处理过程中需要解析的数据,可使用[JSON工具](json-parsing-generation.md)解析。 **示例:** diff --git a/zh-cn/application-dev/arkts-utils/sendablelrucache-recent-list.md b/zh-cn/application-dev/arkts-utils/sendablelrucache-recent-list.md index bb4f40c0e47..2034f08be22 100644 --- a/zh-cn/application-dev/arkts-utils/sendablelrucache-recent-list.md +++ b/zh-cn/application-dev/arkts-utils/sendablelrucache-recent-list.md @@ -1,13 +1,13 @@ # 获取最近访问列表 -为了快速访问最近使用的[Sendable](arkts-sendable.md)对象,从API version 18开始,ArkTS引入了[SendableLruCache](../reference/apis-arkts/js-apis-arkts-utils.md#sendablelrucachek-v18)。开发者可以通过向SendableLruCache实例中添加、删除和获取Sendable对象,实现快速访问最近使用的Sendable对象。本文提供使用SendableLruCache实现获取最近使用列表的开发指导,以书架为例,每次打开一本图书后,需将图书信息更新到最近访问列表中,并在下次访问书架页面时显示最近访问的图书列表。 +为了快速访问最近使用的[Sendable](arkts-sendable.md)对象,从API version 18开始,ArkTS引入了[SendableLruCache](../reference/apis-arkts/js-apis-arkts-utils.md#sendablelrucachek-v18)。开发者可以通过向SendableLruCache实例中添加、删除和获取Sendable对象,实现对最近使用过的Sendable对象的快速访问。本文提供使用SendableLruCache实现最近使用列表的开发指导,以书架为例,每次打开一本图书后,需将图书信息更新到最近访问列表中,下次访问书架页面时显示最近访问的图书列表。 > **说明:** > -> 使用SendableLruCache实例对象时需加锁,避免多线程同时操作导致数据不一致。 +> 使用SendableLruCache实例时需加锁,避免多线程操作导致数据不一致。 > 存放到SendableLruCache实例中的对象应为Sendable对象。 -1. 创建SendableLruCache实例对象,并根据业务需求预设最大容量。
+1. 创建SendableLruCache实例,并预设最大容量以满足业务需求。 此例设置SendableLruCache实例的最大容量为4,用SendableClass类来管理,并导出SendableClass类实例对象。 ```ts @@ -54,7 +54,7 @@ export let lruCache = new SendableClass(); ``` -2. 在Index.ets页面同目录下创建4个图书页面,每个页面显示相应的图书信息,并将每个页面的路径注册到`src/main/resources/base/profile/main_pages.json`文件中。 +2. 在Index.ets页面的同目录下创建4个图书页面,每个页面显示相应图书信息,并将每个页面的路径注册到`src/main/resources/base/profile/main_pages.json`文件中。 ```ts // Book1.ets @@ -198,7 +198,7 @@ } ``` -3. 访问书架页面时,自动展示最近访问的图书列表。 +3. 访问书架页面时,自动显示最近访问的图书列表。 ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md b/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md index 707e7549da3..c8dc8f5cc86 100644 --- a/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md +++ b/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md @@ -1,13 +1,13 @@ # SharedArrayBuffer对象 -SharedArrayBuffer内部包含一块Native内存,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。支持跨并发实例间共享,但是访问及修改需要采用Atomics类,防止数据竞争。SharedArrayBuffer可以用于多个并发实例间的状态共享或者数据共享。通信过程如下图所示: +SharedArrayBuffer 内部包含一块 Native 内存,JS 对象壳分配在虚拟机本地堆。支持跨并发实例间共享,访问和修改需使用 Atomics 类,防止数据竞争。SharedArrayBuffer 可用于多个并发实例间的状态或数据共享。如下图所示: -![sharedarraybufer](figures/sharedarraybufer.png) +![sharedarraybuffer](figures/sharedarraybuffer.png) ## 使用示例 -这里提供了一个示例,使用TaskPool传递Int32Array对象,实现如下: +提供了一个示例,使用 TaskPool 传递 Int32Array 对象,实现如下: ```ts import { taskpool } from '@kit.ArkTS'; diff --git a/zh-cn/application-dev/arkts-utils/sync-task-development.md b/zh-cn/application-dev/arkts-utils/sync-task-development.md index e1b51cf2ba6..94b6d34f18c 100644 --- a/zh-cn/application-dev/arkts-utils/sync-task-development.md +++ b/zh-cn/application-dev/arkts-utils/sync-task-development.md @@ -1,29 +1,32 @@ # 同步任务开发指导 (TaskPool和Worker) -同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。 +同步任务在多个线程之间协调执行,确保任务按顺序和规则执行,防止数据竞争。 -同步任务的实现需要考虑多个线程之间的协作和同步,以确保数据的正确性和程序的正确执行。 +同步任务的实现需考虑线程协作和同步,确保数据正确性和程序正确执行。 -由于TaskPool偏向于单个独立的任务,因此当各个同步任务之间相对独立时推荐使用TaskPool,例如一系列导入的静态方法,或者单例实现的方法。如果同步任务之间有关联性,则需要使用Worker。 +当同步任务相对独立时,推荐使用TaskPool,例如一系列静态方法或单例方法。如果同步任务之间存在关联性,则需要使用Worker。 ## 使用TaskPool处理同步任务 -当需要调度相互独立的任务,或通过静态方法实现的任务,或可以通过单例构造唯一的句柄以及类对象并在不同任务线程之间使用时,推荐使用TaskPool。 +当需要调度相互独立的任务、通过静态方法实现的任务,或在不同任务线程之间使用单例构造的唯一句柄及类对象时,推荐使用TaskPool。 > **说明:** > -> 由于[Actor模型](multi-thread-concurrency-overview.md#actor模型)不同线程间内存隔离的特性,普通单例无法在不同线程间使用。可以通过共享模块导出单例解决该问题。 +> 由于[Actor模型](multi-thread-concurrency-overview.md#actor模型)的线程间内存隔离,普通单例无法跨线程使用。通过共享模块导出单例解决该问题。 -1. 定义并发函数,实现业务逻辑。 +1. 定义并发函数,实现业务逻辑的处理。 -2. 创建任务[Task](../reference/apis-arkts/js-apis-taskpool.md#task),通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute-1)接口执行该任务。 +2. 创建任务[Task](../reference/apis-arkts/js-apis-taskpool.md#task),并通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute-1)接口执行该任务。 -3. 对任务返回的结果进行操作。 +3. 对任务返回的结果进行处理。 -如下示例中业务使用TaskPool调用相关同步方法的代码,首先定义并发函数taskpoolFunc,需要注意必须使用[@Concurrent装饰器](taskpool-introduction.md#concurrent装饰器)装饰该函数;其次定义函数mainFunc,该函数功能为创建任务,执行任务并处理任务返回的结果。 +如下示例中,业务使用TaskPool调用相关同步方法的代码: + +1. 定义并发函数`taskpoolFunc`,必须使用`@Concurrent`装饰器装饰该函数。 +2. 定义函数`mainFunc`,该函数用于创建任务、执行任务并处理任务返回的结果。 ```ts @@ -74,9 +77,9 @@ struct Index { ## 使用Worker处理关联的同步任务 -当一系列同步任务需要使用同一个句柄调度,或者需要依赖某个类对象调度,且无法在不同任务池之间共享时,需要使用Worker。 +当一系列同步任务需要使用同一个句柄调度或依赖某个类对象调度,且无法在不同任务池间共享时,使用Worker。 -1. 在UI主线程中创建Worker对象,同时接收Worker线程发送回来的消息。DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,点击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息。 +1. 在UI主线程中创建Worker对象,接收Worker线程发送的消息。DevEco Studio支持一键生成Worker。在{moduleName}目录下任意位置,点击鼠标右键 > New > Worker,即可生成Worker的模板文件及配置信息。 ```ts // Index.ets @@ -118,7 +121,7 @@ struct Index { ``` -2. 在Worker线程中绑定Worker对象,同时处理同步任务逻辑。 +2. 在Worker线程中绑定Worker对象,并处理同步任务逻辑。 ```ts // handle.ts代码 diff --git a/zh-cn/application-dev/arkts-utils/taskpool-async-task-guide.md b/zh-cn/application-dev/arkts-utils/taskpool-async-task-guide.md index 101484e78d3..ce1252571fc 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-async-task-guide.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-async-task-guide.md @@ -1,9 +1,9 @@ # TaskPool指定任务并发度场景 -此处提供使用TaskPool进行[异步队列](../reference/apis-arkts/js-apis-taskpool.md#asyncrunner18)的开发指导,以相机预览流采集数据处理的功能为例。 -由于处理过程是个频繁耗时任务,如果相机采集过快,就丢弃之前的采集数据,缓存最新的一帧数据处理。 +提供使用TaskPool进行[异步队列](../reference/apis-arkts/js-apis-taskpool.md#asyncrunner18)开发指导,以相机预览流采集数据处理为例。 +处理过程频繁且耗时,若相机采集速度过快,将丢弃先前的采集数据,仅缓存最新一帧进行处理。 -1. 导入需要用到的模块。 +1. 导入所需模块。 ```ts // Index.ets @@ -42,7 +42,7 @@ .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { - // 创建并发度为5的异步队列,等待队列个数为5。 + // 创建并发度为5的异步队列,等待队列个数也为5。 let asyncRunner:taskpool.AsyncRunner = new taskpool.AsyncRunner("async", 5, 5); // 每秒触发一次采集任务 setTimeout(() => { diff --git a/zh-cn/application-dev/arkts-utils/taskpool-communicates-with-mainthread.md b/zh-cn/application-dev/arkts-utils/taskpool-communicates-with-mainthread.md index 8c7c8e032b4..06e6bb3b842 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-communicates-with-mainthread.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-communicates-with-mainthread.md @@ -1,10 +1,10 @@ # TaskPool任务与宿主线程通信 -如果一个Task不仅需要返回最终的执行结果,还需要定时通知宿主线程状态和数据的变化,或者需要分段返回大量数据(例如,从数据库中读取大量数据),可以通过以下方式实现。 +如果一个任务不仅需要返回最终的执行结果,还需要定期通知宿主线程状态和数据的变化,或者需要分段返回大量数据(例如,从数据库中读取大量数据),可以采用以下方法实现。 -下面以多个图片加载任务结果实时返回为例说明。 +下面以多个图片加载任务的实时结果返回为例进行说明。 -1. 首先,实现一个方法,用来接收Task发送的消息。 +1. 首先,实现一个方法以接收Task发送的消息。 ```ts // TaskSendDataUsage.ets @@ -13,7 +13,7 @@ } ``` -2. 然后,在需要执行的Task中,添加sendData()接口将消息发送给宿主线程。 +2. 然后,在需要执行的Task中,添加sendData()接口,将消息发送给宿主线程。 ```ts // IconItemSource.ets @@ -37,7 +37,7 @@ @Concurrent export function loadPictureSendData(count: number): IconItemSource[] { let iconItemSourceList: IconItemSource[] = []; - // 遍历添加6*count个IconItem的数据 + // 遍历添加6*count个IconItem的实例 for (let index = 0; index < count; index++) { const numStart: number = index * 6; // 此处循环使用6张图片资源 @@ -54,8 +54,8 @@ } ``` -3. 最后,在宿主线程通过onReceiveData()接口接收消息。 - 这样宿主线程就可以通过notice()接口接收到Task发送的数据。 +3. 最后,在宿主线程中通过 `onReceiveData()` 接口接收消息。 + 宿主线程可以通过 `notice()` 接口接收 Task 发送的数据。 ```ts // TaskSendDataUsage.ets diff --git a/zh-cn/application-dev/arkts-utils/taskpool-introduction.md b/zh-cn/application-dev/arkts-utils/taskpool-introduction.md index 87b72375616..11918df4444 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-introduction.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-introduction.md @@ -1,22 +1,22 @@ # TaskPool简介 -TaskPool为应用程序提供多线程环境,降低资源消耗、提高系统性能,无需管理线程生命周期。具体接口信息及使用方法详情请见[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)。 +TaskPool提供多线程环境,降低资源消耗,提高系统性能,无需管理线程生命周期。具体接口信息及使用方法请见[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)。 ## TaskPool运作机制 -TaskPool运作机制示意图 +以下是TaskPool运作机制示意图 ![zh-cn_image_0000001964858368](figures/zh-cn_image_0000001964858368.png) -TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,再将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级,同时通过系统统一线程管理,结合动态调度及负载均衡算法,可以节约系统资源。系统默认启动一个任务工作线程,任务多时会扩容。工作线程数量上限取决于设备的物理核数,内部管理具体数量,确保调度和执行效率最优。长时间无任务分发时会缩容,减少工作线程数量。具体扩缩容机制详情请见[TaskPool扩缩容机制](taskpool-introduction.md#taskpool扩缩容机制)。 +TaskPool 支持开发者在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,并将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级。系统通过统一线程管理,结合动态调度和负载均衡算法,节约系统资源。系统默认启动一个任务工作线程,任务多时会自动扩容。工作线程数量上限由设备的物理核数决定,内部管理具体数量,确保调度和执行效率。长时间无任务分发时会缩容,减少工作线程数量。具体扩缩容机制详见 [TaskPool 扩缩容机制](taskpool-introduction.md#taskpool扩缩容机制)。 ## TaskPool注意事项 - 实现任务的函数需要使用[@Concurrent装饰器](#concurrent装饰器)标注,且仅支持在.ets文件中使用。 -- 从API version 11开始,跨并发实例传递带方法的实例对象时,该类必须使用装饰器[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标注,且仅支持在.ets文件中使用。 +- 从API version 11开始,跨并发实例传递带方法的实例对象时,使用装饰器[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标注该类,且仅支持在.ets文件中使用。 -- 任务函数在TaskPool工作线程的执行耗时不能超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)。否则,任务将被强制终止。 +- 任务函数在TaskPool工作线程中的执行时间不得超过180秒(不包括Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)。否则,任务将被强制终止。 - 实现任务的函数入参需满足序列化支持的类型,详情请参见[线程间通信对象](interthread-communication-overview.md)。目前不支持使用[@State装饰器](../ui/state-management/arkts-state.md)、[@Prop装饰器](../ui/state-management/arkts-prop.md)、[@Link装饰器](../ui/state-management/arkts-link.md)等装饰器修饰的复杂类型。 @@ -47,41 +47,41 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 } ``` -- 由于不同线程中上下文对象是不同的,因此TaskPool工作线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。 +- 由于不同工作线程中上下文对象是不同的,因此TaskPool工作线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。 - 序列化传输的数据量限制为16MB。 -- [Priority](../reference/apis-arkts/js-apis-taskpool.md#priority)的IDLE优先级是用来标记需要在后台运行的耗时任务(例如数据同步、备份),它的优先级别是最低的。这种优先级的任务只在所有线程都空闲时触发执行,并且只会占用一个线程。 +- [Priority](../reference/apis-arkts/js-apis-taskpool.md#priority)的IDLE优先级用于标记需要在后台运行的耗时任务(例如数据同步、备份)。它的优先级别是最低的。这种优先级的任务只在所有线程都空闲时触发执行,并且只会占用一个线程。 - Promise不支持跨线程传递。TaskPool返回pending或rejected状态的Promise时失败,返回fulfilled状态的Promise时TaskPool会解析返回的结果,如果结果可以跨线程传递,则返回成功。 - 不支持在TaskPool工作线程中使用[AppStorage](../ui/state-management/arkts-appstorage.md)。 -- TaskPool支持开发者在宿主线程封装任务并提交给任务队列,理论上支持的任务数量没有上限。然而,任务的执行效率受限于任务的优先级和系统资源。当工作线程达到最大数量时,任务的执行效率可能会下降。 +- TaskPool 支持开发者在宿主线程封装任务并提交给任务队列,理论上支持无限数量的任务。任务的执行效率取决于任务的优先级和系统资源。如果工作线程达到最大数量,任务的执行效率可能会下降。 -- TaskPool不支持指定任务所运行的线程,任务会被分配到空闲的线程中执行。如果需要指定任务所运行的线程,建议使用[Worker](worker-introduction.md)。 +- TaskPool不支持指定任务所运行的工作线程,任务会被分配到空闲的工作线程中执行。如果需要指定任务所运行的工作线程,建议使用[Worker](worker-introduction.md)。 -## \@Concurrent装饰器 +## @Concurrent 装饰器 -在使用[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)时,执行的并发函数需要使用该装饰器修饰,否则无法通过相关校验。 +使用[TaskPool]时,执行的并发函数需要使用@Concurrent装饰器修饰。 > **说明:** > -> 从API version 9开始,支持使用\@Concurrent装饰器声明并校验并发函数。 +> API version 9开始支持使用@Concurrent装饰器声明并校验并发函数。 ### 装饰器说明 -| \@Concurrent并发装饰器 | 说明 | +| @Concurrent并发装饰器 | 说明 | | -------- | -------- | | 装饰器参数 | 无。 | | 使用场景 | 仅支持在Stage模型的工程中使用。仅支持在.ets文件中使用。 | -| 装饰的函数类型 | 允许标注async函数或普通函数。禁止标注generator、箭头函数、类方法。不支持类成员函数或者匿名函数。 | +| 装饰的函数类型 | 允许标注async函数或普通函数。禁止标注generator、箭头函数、类方法。不支持类成员函数。不支持匿名函数。 | | 装饰的函数内的变量类型 | 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量。 | -| 装饰的函数内的返回值类型 | 支持的类型请查[线程间通信对象](interthread-communication-overview.md)。 | +| 装饰的函数内的返回值类型 | 支持的类型请参见[线程间通信对象]。 | > **说明:** > -> 由于\@Concurrent标记的函数不能访问闭包,因此函数内部不能调用当前文件的其他函数,例如: +> 由于@Concurrent标记的函数不能访问闭包,因此函数内部不能调用当前文件的其他函数。 > > ```ts > function bar() { @@ -97,7 +97,7 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 #### 并发函数一般使用 -并发函数为一个计算两数之和的普通函数,taskpool执行该函数并返回结果。 +并发函数计算两数之和,`taskpool`执行该函数并返回结果。 示例: @@ -142,7 +142,7 @@ struct Index { #### 并发函数返回Promise -并发函数中返回Promise时需要特别关注。如示例所示,testPromise和testPromise1等需处理Promise并返回结果。 +在并发函数中返回Promise时需特别关注。例如,`testPromise`和`testPromise1`等函数需处理Promise并返回结果。 示例: @@ -253,7 +253,7 @@ struct Index { #### 并发函数中使用自定义类或函数 -在并发函数中使用自定义类或函数时,需将其定义在不同的文件中,否则会被认为是闭包。如以下示例所示。 +在并发函数中使用自定义类或函数时,需将其定义在单独的文件中,否则会被视为闭包。如下示例所示。 示例: @@ -353,7 +353,7 @@ export class MyTestB { #### 并发异步函数中使用Promise -在并发异步函数中使用Promise时,建议搭配await使用。这样TaskPool可以捕获Promise中的异常。推荐使用示例如下。 +在并发异步函数中使用Promise时,建议搭配await使用,这样TaskPool可以捕获异常。推荐使用示例如下。 示例: @@ -431,11 +431,11 @@ struct Index { ### 扩容机制 -一般情况下,开发者向任务队列提交任务时会触发扩容检测。扩容检测首先判断当前空闲的工作线程数是否大于任务数,如果大于,说明线程池中存在空闲工作线程,无需扩容。否则,通过负载计算确定所需工作线程数并创建。 +开发者向任务队列提交任务时,系统会触发扩容检测。扩容检测首先判断当前空闲的工作线程数是否大于任务数。如果大于,说明线程池中存在空闲工作线程,无需扩容。否则,通过负载计算确定所需工作线程数并创建。 ### 缩容机制 -扩容后,TaskPool新建多个工作线程,但当任务数减少后,这些线程就会处于空闲状态,造成资源浪费,因此TaskPool提供缩容机制。TaskPool使用了定时器,定时检测当前负载。定时器30s触发一次,每次尝试释放空闲的工作线程。释放的线程需要满足如下条件: +扩容后,TaskPool会新建多个工作线程。当任务数减少时,这些线程会处于空闲状态,造成资源浪费。因此,TaskPool提供了缩容机制。TaskPool使用定时器,每30秒检测一次当前负载,尝试释放空闲的工作线程。释放的线程需满足以下条件: - 该线程空闲时长达到30s。 diff --git a/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md b/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md index 80854ad3f2a..d747244fb96 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md @@ -1,10 +1,10 @@ -# TaskPool和Worker的对比 (TaskPool和Worker) +# TaskPool和Worker的对比 -TaskPool和Worker的作用是为应用程序提供一个多线程的运行环境,用于处理耗时的计算任务或其他密集型任务。可以避免任务阻塞宿主线程,从而提高系统性能和资源利用率。 +TaskPool和Worker的作用是为应用程序提供多线程运行环境,用于处理耗时的计算任务或其他密集型任务,避免任务阻塞宿主线程,从而提高系统性能和资源利用率。 -本文将从[实现特点](#实现特点对比)和[适用场景](#适用场景对比)两个方面来进行TaskPool与Worker的比较。 +本文将从实现特点和适用场景两个方面比较TaskPool与Worker。 ## 实现特点对比 @@ -34,18 +34,18 @@ TaskPool和Worker的作用是为应用程序提供一个多线程的运行环境 ## 适用场景对比 -TaskPool和Worker均支持多线程并发能力。由于TaskPool的工作线程会绑定系统的调度优先级,并支持负载均衡(自动扩缩容),相比之下,Worker需要开发者自行创建,存在创建耗时。因此,性能方面TaskPool优于Worker,推荐在大多数场景中使用TaskPool。 +TaskPool和Worker均支持多线程并发能力。由于TaskPool的工作线程会绑定系统的调度优先级,并支持负载均衡(自动扩缩容),相比之下,Worker需要开发者自行创建,存在创建时间较长的问题。因此,性能方面TaskPool优于Worker,推荐在大多数场景中使用TaskPool。 -TaskPool偏向独立任务维度,该任务在线程中执行,无需关注线程的生命周期,超长任务(大于3分钟且非长时任务)会被系统自动回收。而Worker偏向线程的维度,支持长时间占据线程执行,需要开发者主动管理线程生命周期。 +TaskPool 侧重于独立任务的维度,任务在线程中执行时,无需关注线程的生命周期。系统会自动回收超长任务(大于3分钟且非长时任务)。而 Worker 则侧重于线程的维度,支持长时间占据线程执行,需要开发者主动管理线程的生命周期。 -常见开发场景及适用说明如下: +常见的开发场景及适用说明如下: -- 运行时间超过3分钟的任务(不包括Promise和async/await异步调用的耗时,如网络下载、文件读写等I/O任务的耗时):例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker。场景示例可参考[常驻任务开发指导](resident-task-guide.md)。 +- 运行时间超过3分钟的任务(不包括异步调用的耗时,如网络下载、文件读写等I/O任务):例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker。更多场景示例请参考[常驻任务开发指导](resident-task-guide.md)。 -- 有关联的一系列同步任务:例如在一些需要创建、使用句柄的场景中,句柄每次创建都是不同的,该句柄需永久保存,保证使用该句柄进行操作,需要使用Worker。场景示例可参考[使用Worker处理关联的同步任务](sync-task-development.md#使用worker处理关联的同步任务)。 +- 在需要创建和使用句柄的场景中,每次创建的句柄都不同,必须永久保存该句柄,确保后续操作使用同一句柄。建议使用Worker处理这些关联的同步任务。详细示例请参阅[使用Worker处理关联的同步任务](sync-task-development.md#使用worker处理关联的同步任务)。 -- 需要设置优先级的任务:在API version 18 之前,Worker不支持设置调度优先级,需要使用TaskPool。从API version 18 开始,Worker支持设置调度优先级,开发者可以根据使用场景和任务特性选择使用TaskPool或Worker。例如[图库直方图绘制场景](cpu-intensive-task-development.md#使用taskpool进行图像直方图处理),后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,且任务相对独立,推荐使用TaskPool。 +- 在API版本18之前,Worker不支持设置调度优先级,需使用TaskPool。从API版本18起,Worker支持设置调度优先级。开发者可根据使用场景和任务特性选择TaskPool或Worker。例如,在图库直方图绘制场景中,后台计算的直方图数据用于前台界面显示,影响用户体验,需高优先级处理且任务相对独立,推荐使用TaskPool。 -- 需要频繁取消的任务:例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,往一侧滑动跳到下一张图片时,要取消另一侧的一个缓存任务,需要使用TaskPool。 +- 需要频繁取消的任务,例如图库大图浏览场景。为了提升体验,会同时缓存当前图片左右各2张图片。当往一侧滑动跳到下一张图片时,需取消另一侧的缓存任务,使用TaskPool。 -- 大量或调度点分散的任务:例如大型应用的多个模块包含多个耗时任务,不方便使用Worker去做负载管理,推荐使用TaskPool。场景示例可参考[批量数据写数据库场景](batch-database-operations-guide.md)。 +- 对于调度点分散或包含多个耗时任务的大型应用模块,推荐使用TaskPool进行任务管理。有关场景示例,请参阅[批量数据写数据库场景](batch-database-operations-guide.md)。 diff --git a/zh-cn/application-dev/arkts-utils/taskpool-waterflow.md b/zh-cn/application-dev/arkts-utils/taskpool-waterflow.md index b5795209e67..96414ada571 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-waterflow.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-waterflow.md @@ -1,12 +1,12 @@ # ArkUI瀑布流渲染场景 -此处提供使用任务池[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)提升[WaterFlow瀑布流](../reference/apis-arkui/arkui-ts/ts-container-waterflow.md)渲染性能的开发指导。UI线程查询数据库数据,并将数据渲染到瀑布流组件,数据过大时会导致UI线程长时间等待,影响用户体验。因此,我们可以将数据查询操作放到子线程中,并通过TaskPool的接口返回数据给UI线程。 +提供使用任务池[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)提升[WaterFlow瀑布流](../reference/apis-arkui/arkui-ts/ts-container-waterflow.md)渲染性能的开发指导。查询数据库数据并在瀑布流组件中渲染。数据量大时,会导致UI线程长时间等待,影响用户体验。因此,将数据查询操作移到子线程中,并通过TaskPool接口将数据返回给UI线程。 本示例说明以下场景: - 模拟子线程[读取数据库数据](batch-database-operations-guide.md)并返回给UI线程。 - UI线程感知到数据更新,将子线程返回的数据渲染到瀑布流组件。 -1. 定义一个接口,用于子线程查询数据库并将数据返回给UI线程。 +1. 定义一个接口,子线程查询数据库并返回数据给UI线程。 ```ts // Mock.ets @@ -25,14 +25,14 @@ export function getImgFromDB() { - //此处模拟查询数据库,并返回数据 + //此处执行查询数据库的操作,并返回数据 let task = new taskpool.Task(query); task.onReceiveData(fillImg); taskpool.execute(task); } ``` -2. 封装一个瀑布流数据源,用于瀑布流组件加载数据。 +2. 封装瀑布流数据源,用于加载数据。 ```ts // WaterFlowDataSource.ets @@ -127,7 +127,7 @@ this.notifyDataAdd(this.dataArray.length - 1); } - // 在指定索引位置增加一个元素 + // 在指定索引位置添加一个元素 public addItem(index: number): void { this.dataArray.splice(index, 0, this.dataArray.length); this.notifyDataAdd(index); @@ -148,7 +148,7 @@ // 删除最后一个元素 public deleteLastItem(): void { this.dataArray.splice(-1, 1); - this.notifyDataDelete(this.dataArray.length); + this.notifyDataDelete(this.dataArray.length - 1); } // 在指定索引位置删除一个元素 @@ -166,7 +166,7 @@ } ``` -3. 在应用冷启动阶段,调用`getImgFromDB()`接口,将数据查询操作放到子线程中。在`img`接收到子线程返回的数据后,将数据渲染到瀑布流组件。 +3. 在应用冷启动阶段,调用 `getImgFromDB()` 接口,将数据查询操作放到子线程中。子线程返回数据后,将数据渲染到瀑布流组件。 ```ts // Index.ets @@ -237,7 +237,7 @@ .onClick(()=>{ }); - // 为了模拟图片加载,使用Text组件显示,正常加载jpg文件时,可以直接使用Image组件,参考Image(this.img[item % 33]).objectFit(ImageFit.Contain).width('100%').layoutWeight(1) + // 为了模拟图片加载,使用 Text 组件显示。在正常加载 JPG 文件时,可以直接使用 Image 组件。参考以下代码:Image(this.img[item % 33]).objectFit(ImageFit.Contain).width('100%').layoutWeight(1) if (img[item % 33] == null) { Text("图片加载中...") .width('100%') diff --git a/zh-cn/application-dev/arkts-utils/time-consuming-task-overview.md b/zh-cn/application-dev/arkts-utils/time-consuming-task-overview.md index c75c02842ae..edb7ce06575 100644 --- a/zh-cn/application-dev/arkts-utils/time-consuming-task-overview.md +++ b/zh-cn/application-dev/arkts-utils/time-consuming-task-overview.md @@ -1,7 +1,7 @@ # 耗时任务并发场景简介 -耗时任务是指需要较长时间执行的任务,如果在UI主线程执行,可能导致应用卡顿、掉帧或响应延迟。典型的耗时任务包括CPU密集型任务、I/O密集型任务和同步任务。 +耗时任务是指需要长时间执行的任务,如果在UI主线程执行,可能导致应用卡顿、掉帧或响应延迟。耗时任务包括CPU密集型任务、I/O密集型任务和同步任务。 常见的业务场景分类如下: @@ -9,9 +9,9 @@ | 常见业务场景 | 具体业务描述 | CPU密集型 | I/O密集型 | 同步任务 | | -------- | -------- | -------- | -------- | -------- | -| 图片/视频编解码 | 将图片或视频进行编解码再展示。 | √ | √ | × | -| 压缩/解压缩 | 解压本地压缩包或压缩本地文件。 | √ | √ | × | -| JSON解析 | 序列化和反序列化JSON字符串。 | √ | × | × | -| 模型运算 | 对数据进行模型运算分析等。 | √ | × | × | -| 网络下载 | 密集网络请求下载资源、图片、文件等。 | × | √ | × | -| 数据库操作 | 将聊天记录、页面布局信息、音乐列表信息等保存到数据库,或者应用二次启动时,读取数据库展示相关信息。 | × | √ | × | +| 图片/视频编解码 | 编解码图片或视频并展示。 | √ | √ | × | +| 压缩/解压缩 | 解压或压缩本地文件。 | √ | √ | × | +| JSON解析 | 序列化和反序列化JSON。 | √ | × | × | +| 模型运算 | 对数据进行模型运算。 | √ | × | × | +| 网络下载 | 密集网络请求下载资源。 | × | √ | × | +| 数据库操作 | 保存聊天记录、页面布局信息、音乐列表信息到数据库。应用二次启动时,读取数据库信息。 | × | √ | × | diff --git a/zh-cn/application-dev/arkts-utils/transferabled-object.md b/zh-cn/application-dev/arkts-utils/transferabled-object.md index fe8204ff864..bf5ab255ec4 100644 --- a/zh-cn/application-dev/arkts-utils/transferabled-object.md +++ b/zh-cn/application-dev/arkts-utils/transferabled-object.md @@ -1,33 +1,33 @@ # Transferable对象(NativeBinding对象) -Transferable对象,也称为NativeBinding对象,是指绑定C++对象的JS对象,主体功能由C++提供,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。跨线程传输时复用同一个C++对象,相比于JS对象的拷贝模式,传输效率高。因此,可共享或转移的NativeBinding对象也被称为Transferable对象。 +Transferable对象,即NativeBinding对象,绑定C++对象的JS对象,主体功能由C++提供,JS对象壳分配在虚拟机本地堆。跨线程传输时复用同一个C++对象,传输效率高于JS对象的拷贝模式。因此,NativeBinding对象也称为Transferable对象。 ## 共享模式 -如果C++实现能够保证线程安全性,则这个NativeBinding对象的C++部分支持共享传输。此时,NativeBinding对象跨线程传输后,只需要重新创建JS壳,就可以桥接到相同的C++对象上。通信过程如下图所示: +如果C++实现保证线程安全性,NativeBinding对象的C++部分支持共享传输。跨线程传输后,重新创建JS壳即可桥接到相同的C++对象上。通信过程如下图所示: ![nativeBinding](figures/nativeBinding.png) -常见的共享模式NativeBinding对象包括Context对象,它包含应用程序组件的上下文信息,提供访问系统服务和资源的方式,使得应用程序组件可以与系统进行交互。获取Context信息的方法可以参考[获取上下文信息](../application-models/application-context-stage.md)。 +常见的共享模式NativeBinding对象包括Context对象,它提供应用程序组件与系统交互所需的上下文信息和访问系统服务、资源的方式。获取Context信息的方法可参考[获取上下文信息](../application-models/application-context-stage.md)。 示例可参考[使用TaskPool进行频繁数据库操作](batch-database-operations-guide.md#使用taskpool进行频繁数据库操作)。 ## 转移模式 -如果C++实现包含数据,且无法保证线程安全性,则NativeBinding对象的C++部分需要采用转移方式传输。NativeBinding对象跨线程传输后,重新创建JS壳即可桥接到C++对象上,但需移除原对象的绑定关系。通信过程如下图所示: +如果C++实现包含数据且无法保证线程安全性,NativeBinding对象的C++部分需要通过转移方式传输。跨线程传输后,重新创建JS壳即可桥接到C++对象上,但需解除原对象的绑定关系。通信过程如下图所示: ![nativeBinding_transfer](figures/nativeBinding_transfer.png) -常见的转移模式NativeBinding对象包括[PixelMap对象](../reference/apis-image-kit/js-apis-image.md#imagecreatepixelmap8),它可以读取或写入图像数据,获取图像信息,常用于显示图片。 +常见的转移模式NativeBinding对象包括[PixelMap对象](../reference/apis-image-kit/js-apis-image.md#imagecreatepixelmap8)。它可以读取或写入图像数据,获取图像信息,常用于显示图片。 ### 使用示例 -这里提供了一个跨线程传递PixelMap对象的示例以帮助更好理解。首先获取rawfile文件夹中的图片资源,然后在子线程中创建PixelMap对象传递给主线程,具体实现如下: +这里提供了一个跨线程传递PixelMap对象的示例,以帮助更好地理解。首先从rawfile文件夹中获取图片资源,然后在子线程中创建PixelMap对象并传递给主线程,具体实现如下: ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/worker-communicates-with-mainthread.md b/zh-cn/application-dev/arkts-utils/worker-communicates-with-mainthread.md index d502afaa0f4..6312566bfeb 100644 --- a/zh-cn/application-dev/arkts-utils/worker-communicates-with-mainthread.md +++ b/zh-cn/application-dev/arkts-utils/worker-communicates-with-mainthread.md @@ -1,7 +1,7 @@ # Worker和宿主线程的即时消息通信 -在ArkTS中,Worker相对于Taskpool存在一定的差异性,有数量限制但是可以长时间存在。一个[Worker](worker-introduction.md)中可能会执行多个不同的任务,每个任务的执行时长或返回结果可能都不同,宿主线程需要根据情况调用Worker中的不同方法,Worker则需要及时地将结果返回给宿主线程。 +在ArkTS中,Worker相对于任务池存在差异,有数量限制但可以长时间存在。一个[Worker](worker-introduction.md)可以执行多个任务,每个任务的执行时间和返回结果可能不同。宿主线程需根据情况调用Worker中的不同方法,Worker则需及时将结果返回给宿主线程。 下面以Worker响应"hello world"请求为例说明。 @@ -22,7 +22,7 @@ } ``` -2. 这里的宿主线程是UI主线程,在宿主线程中创建Worker对象,当点击Button时调用postMessage向Worker线程发送消息,通过Worker的onmessage方法接收Worker线程返回的数据。 +2. 这里的UI主线程是UI主线程,在UI主线程中创建Worker对象。点击Button时,调用postMessage向Worker线程发送消息,并通过Worker的onmessage方法接收返回的数据。 ```ts // Index.ets @@ -87,4 +87,4 @@ ``` -在示例代码中,Worker接收宿主线程的消息,并进行处理后将结果返回给宿主线程。实现了宿主线程与Worker之间的即时通信,使宿主线程能够方便地使用Worker的运行结果。 +示例代码中,Worker接收宿主线程的消息,处理后返回结果。这实现了宿主线程与Worker的即时通信,方便使用Worker的运行结果。 diff --git a/zh-cn/application-dev/arkts-utils/worker-introduction.md b/zh-cn/application-dev/arkts-utils/worker-introduction.md index 08b3859362a..208155363df 100644 --- a/zh-cn/application-dev/arkts-utils/worker-introduction.md +++ b/zh-cn/application-dev/arkts-utils/worker-introduction.md @@ -1,6 +1,6 @@ # Worker简介 -Worker的主要作用是为应用程序提供一个多线程的运行环境,满足应用程序在执行过程中与宿主线程分离,在后台线程中运行脚本进行耗时操作,避免计算密集型或高延迟的任务阻塞宿主线程。具体接口信息及使用方法详情请见[Worker](../reference/apis-arkts/js-apis-worker.md)。 +Worker提供多线程环境,使应用程序与宿主线程分离,在后台线程中运行脚本,避免阻塞宿主线程。具体接口信息见[Worker](../reference/apis-arkts/js-apis-worker.md)。 ## Worker运作机制 @@ -9,17 +9,17 @@ Worker的主要作用是为应用程序提供一个多线程的运行环境, ![worker](figures/worker.png) -创建Worker的线程称为宿主线程(不一定是主线程,工作线程也支持创建Worker子线程)。Worker子线程(或Actor线程、工作线程)是Worker自身运行的线程。每个Worker子线程和宿主线程拥有独立的实例,包含基础设施、对象、代码段等。因此,启动每个Worker存在一定的内存开销,需要限制Worker子线程的数量。Worker子线程和宿主线程通过消息传递机制通信,利用序列化机制完成命令和数据的交互。 +创建Worker的线程称为宿主线程,该线程可以是主线程或工作线程。Worker子线程是Worker自身运行的线程。每个Worker子线程和宿主线程都拥有独立的实例,包括基础设施、对象和代码段。因此,启动每个Worker会带来一定的内存开销,需要限制Worker子线程的数量。Worker子线程和宿主线程通过消息传递机制通信,利用序列化机制完成命令和数据的交互。 ## Worker注意事项 - 创建Worker时,提供手动和自动两种创建方式,手动创建Worker线程目录及文件时,需同步进行相关配置,具体要求请参阅[创建Worker的注意事项](#创建worker的注意事项)。 -- 使用Worker能力时,构造函数中传入的Worker线程文件的路径在不同版本有不同的规则,详情请参见[文件路径注意事项](#文件路径注意事项)。 -- Worker创建后需要手动管理生命周期。同时运行的Worker子线程数量最多为64个,并且与[napi_create_ark_runtime](../reference/native-lib/napi.md#napi_create_ark_runtime)创建的runtime总数不超过80。详情请参见[生命周期注意事项](#生命周期注意事项)。 -- 不同线程中上下文对象是不同的,因此Worker线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。 +- 使用Worker时,构造函数中传入的Worker线程文件路径在不同版本有不同的规则。详情请参见[文件路径注意事项](#文件路径注意事项)。 +- 创建Worker后,需手动管理其生命周期。同时运行的Worker子线程数量不得超过64个,且与通过`napi_create_ark_runtime`创建的runtime总数不得超过80。详细信息请参见[生命周期注意事项](#生命周期注意事项)。 +- 不同线程中上下文对象是不同的,因此Worker子线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。 - 序列化传输的数据量大小限制为16MB。 -- 使用Worker模块时,API version 18及之后的版本建议在宿主线程中注册onAllErrors回调,以捕获Worker线程生命周期内的各种异常。API version 18之前的版本应注册onerror回调。如果未注册onAllErrors或onerror接口,当Worker线程出现异常时会发生jscrash问题。需要注意的是,onerror接口仅能捕获onmessage回调中的同步异常,捕获异常后,Worker线程将进入销毁流程,无法继续使用。详情请参见[onAllErrors接口与onerror接口之间的行为差异](#onallerrors接口与onerror接口之间的行为差异)。 +- 在使用Worker模块时,API版本18及更高版本建议在宿主线程中注册onAllErrors回调,以捕获Worker线程生命周期内的所有异常。API版本18之前的版本应注册onerror回调。如果未注册onAllErrors或onerror接口,Worker线程出现异常时将导致jscrash问题。请注意,onerror接口仅能捕获onmessage回调中的同步异常,捕获异常后,Worker线程将被销毁,无法继续使用。详情请参见[onAllErrors接口与onerror接口之间的行为差异](#onallerrors接口与onerror接口之间的行为差异)。 - 不支持跨HAP使用Worker线程文件。 - 引用HAR/HSP中的worker前,需要先配置对HAR/HSP的依赖,详见[引用共享包](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-har-import)。 - 不支持在Worker工作线程中使用[AppStorage](../ui/state-management/arkts-appstorage.md)。 @@ -29,7 +29,7 @@ Worker的主要作用是为应用程序提供一个多线程的运行环境, Worker线程文件需要放在"{moduleName}/src/main/ets/"目录层级之下,否则不会被打包到应用中。有手动和自动两种创建Worker线程目录及文件的方式。 -- 手动创建:开发者手动创建相关目录及文件,通常是在ets目录下创建一个workers文件夹,用于存放worker.ets文件,需要配置build-profile.json5的相关字段信息,确保Worker线程文件被打包到应用中。 +- 手动创建相关目录及文件,通常在ets目录下创建workers文件夹,存放worker.ets文件。配置build-profile.json5的字段信息,确保Worker线程文件被打包到应用中。 Stage模型: @@ -60,7 +60,7 @@ Worker线程文件需要放在"{moduleName}/src/main/ets/"目录层级之下, ### 文件路径注意事项 - 当使用Worker模块具体功能时,均需先构造Worker实例对象,其构造函数与API版本相关,且构造函数需要传入Worker线程文件的路径(scriptURL)。 +使用Worker模块的具体功能时,需先构造Worker实例对象。构造函数与API版本相关,需传入Worker线程文件的路径(scriptURL)。 ```ts // 导入模块 @@ -82,7 +82,7 @@ const worker2: worker.Worker = new worker.Worker('entry/ets/workers/worker.ets') 1) 加载Ability中Worker线程文件场景 -加载Ability中的worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 +加载Ability中Worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 ```ts import { worker } from '@kit.ArkTS'; @@ -96,7 +96,7 @@ const workerStage2: worker.ThreadWorker = new worker.ThreadWorker('testworkers/e 2) 加载[HSP](../quick-start/in-app-hsp.md)中Worker线程文件场景 -加载HSP中worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 +加载HSP中Worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 ```ts import { worker } from '@kit.ArkTS'; @@ -107,15 +107,15 @@ const workerStage3: worker.ThreadWorker = new worker.ThreadWorker('hsp/ets/worke 3) 加载[HAR](../quick-start/har-package.md)中Worker线程文件场景 -加载HAR中worker线程文件存在以下两种情况: +加载HAR中Worker线程文件存在以下两种情况: - @标识路径加载形式:所有种类的模块加载本地HAR中的Worker线程文件,加载路径规则:@{moduleName}/ets/{relativePath}。 -- 相对路径加载形式:本地HAR加载该包内的Worker线程文件,加载路径规则:创建Worker对象所在文件与Worker线程文件的相对路径。 +- 相对路径加载形式:本地HAR加载该包内的Worker线程文件。加载路径规则:创建Worker对象所在文件与Worker线程文件的相对路径。 >**说明:** > ->当开启useNormalizedOHMUrl(在工程目录中与entry同级别的应用级build-profile.json5文件中,将strictMode属性下的useNormalizedOHMUrl字段配置为true)或HAR包被打包成三方包使用时,HAR包中使用Worker仅支持通过相对路径的加载形式创建。 +当在应用级 `build-profile.json5` 文件中开启 `useNormalizedOHMUrl`(将 `strictMode` 属性下的 `useNormalizedOHMUrl` 字段配置为 `true`)或 HAR 包被打包成三方包时,HAR 包中使用 Worker 仅支持通过相对路径创建。 ```ts import { worker } from '@kit.ArkTS'; @@ -153,10 +153,10 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ### 生命周期注意事项 -- Worker的创建和销毁会消耗较多的系统资源,建议开发者合理管理已创建的Worker并重复使用。Worker空闲时仍会占用资源,因此当不需要Worker时,可以调用[terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9)接口或[close()](../reference/apis-arkts/js-apis-worker.md#close9)方法主动销毁Worker。若Worker处于已销毁或正在销毁等非运行状态时,调用其功能接口,会抛出相应的错误。 +Worker的创建和销毁消耗较多系统资源,建议合理管理已创建的Worker并重复使用。空闲时Worker仍占用资源,因此不再需要时,应调用`terminate()`接口或`close()`方法主动销毁Worker。若Worker处于已销毁或正在销毁等非运行状态,调用其功能接口会抛出错误。 -- Worker的数量由内存管理策略决定,设定的内存阈值为1.5GB和设备物理内存的60%中的较小者。在内存允许的情况下,系统最多可以同时运行64个Worker。如果尝试创建的Worker数量超出这一上限,系统将抛出错误:“Worker initialization failure, the number of workers exceeds the maximum.”。实际运行的Worker数量会根据当前内存使用情况实时调整。当所有Worker和主线程的累积内存占用超过设定的阈值时,系统将触发内存溢出(OOM)错误,导致应用程序崩溃。 +- Worker数量由内存管理策略决定,内存阈值为1.5GB和设备物理内存的60%中的较小者。系统最多同时运行64个Worker。尝试创建的Worker数量超出上限时,系统将抛出错误:“Worker initialization failure, the number of workers exceeds the maximum.”。实际运行的Worker数量会根据当前内存使用情况实时调整。所有Worker和主线程的累积内存占用超过阈值时,系统将触发内存溢出(OOM)错误,导致应用程序崩溃。 ### onAllErrors接口与onerror接口之间的行为差异 @@ -184,18 +184,18 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ## Worker基本用法示例 -1. DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,单击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息。本文以创建“worker”为例。 +DevEco Studio支持一键生成Worker。在{moduleName}目录下任意位置,单击鼠标右键,选择New > Worker,即可自动生成Worker的模板文件及配置信息。本文以创建“Worker”为例。 - 此外,支持手动创建Worker文件,具体方式和注意事项请参阅[创建Worker的注意事项](#创建worker的注意事项)。 +支持手动创建Worker文件。具体方式和注意事项请参阅[创建Worker的注意事项](#创建worker的注意事项)。 -2. 导入Worker模块。 +2. 创建Worker模块。 ```ts // Index.ets import { ErrorEvent, MessageEvents, worker } from '@kit.ArkTS' ``` -3. 在宿主线程中通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,并注册回调函数。 +3. 在宿主线程中调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,并注册回调函数。 ```ts // Index.ets @@ -216,27 +216,27 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke }) .onClick(() => { // 创建Worker对象 - let workerInstance = new worker.ThreadWorker('entry/ets/workers/worker.ets'); + let workerInstance = new worker.ThreadWorker('entry/ets/workers/Worker.ets'); - // 注册onmessage回调,当宿主线程接收到来自其创建的Worker通过workerPort.postMessage接口发送的消息时被调用,在宿主线程执行 + // 注册onmessage回调,接收Worker发送的消息,在宿主线程执行 workerInstance.onmessage = (e: MessageEvents) => { let data: string = e.data; console.info('workerInstance onmessage is: ', data); } - // 注册onAllErrors回调,可以捕获Worker线程的onmessage回调、timer回调以及文件执行等流程产生的全局异常,在宿主线程执行 + // 注册onAllErrors回调,捕获Worker线程的全局异常,在宿主线程执行 workerInstance.onAllErrors = (err: ErrorEvent) => { console.info('workerInstance onAllErrors message is: ' + err.message); } - // 注册onmessageerror回调,当Worker对象接收到无法序列化的消息时被调用,在宿主线程执行 + // 注册onmessageerror回调,处理无法序列化的消息,在宿主线程执行 workerInstance.onmessageerror = () => { console.info('workerInstance onmessageerror'); } - // 注册onexit回调,当Worker销毁时被调用,在宿主线程执行 + // 注册 `onexit` 回调,当 Worker 销毁时在宿主线程执行。 workerInstance.onexit = (e: number) => { - // 如果Worker正常退出,code为0;如果异常退出,code为1 + // Worker正常退出时,code为0;异常退出时,code为1。 console.info('workerInstance onexit code is: ', e); } @@ -258,7 +258,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke const workerPort: ThreadWorkerGlobalScope = worker.workerPort; - // 注册onmessage回调,当Worker线程收到来自其宿主线程通过postMessage接口发送的消息时被调用,在Worker线程执行 + // 注册onmessage回调,当Worker线程收到来自主线程通过postMessage接口发送的消息时调用,执行回调函数 workerPort.onmessage = (e: MessageEvents) => { let data: string = e.data; console.info('workerPort onmessage is: ', data); @@ -267,12 +267,12 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke workerPort.postMessage('2'); } - // 注册onmessageerror回调,当Worker对象接收到一条无法被序列化的消息时被调用,在Worker线程执行 + // 注册onmessageerror回调,当Worker对象接收到无法序列化的消息时调用,执行回调函数 workerPort.onmessageerror = () => { console.info('workerPort onmessageerror'); } - // 注册onerror回调,当Worker在执行过程中发生异常被调用,在Worker线程执行 + // 注册onerror回调,处理Worker执行过程中的异常,在Worker线程执行 workerPort.onerror = (err: ErrorEvent) => { console.info('workerPort onerror err is: ', err.message); } @@ -281,9 +281,9 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ## 跨har包加载Worker -1. 创建har详情参考[开发静态共享包](../quick-start/har-package.md)。 +1. 创建HAR详情,请参考[开发静态共享包](../quick-start/har-package.md)。 -2. 在har中创建Worker线程文件相关内容。 +2. 在HAR中创建Worker线程文件。 ```ts // worker.ets @@ -293,7 +293,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke } ``` -3. 在entry模块的oh-package.json5文件中配置har包的依赖。 +3. 在entry模块的oh-package.json5文件中配置HAR包依赖。 ```ts // 在entry模块配置har包的依赖 @@ -310,7 +310,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke } ``` -4. 在entry模块中加载har包中的Worker线程文件。 +4. 在entry模块中加载HAR包的Worker线程文件。 ```ts // Index.ets @@ -348,7 +348,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ## 多级Worker生命周期管理 -支持创建多级Worker,即父Worker可以创建子Worker,形成层级线程关系。由于Worker线程的生命周期由开发者自行管理,因此需要正确管理多级Worker的生命周期。如果销毁父Worker时未能终止其子Worker的运行,可能会导致不可预期的结果。因此需确保子Worker的生命周期在父Worker生命周期范围内,销毁父Worker前,先销毁所有子Worker。 +支持创建多级Worker,即父Worker可以创建子Worker,形成层级线程关系。开发者需正确管理多级Worker的生命周期。销毁父Worker前,必须先销毁所有子Worker,以避免不可预期的结果。确保子Worker的生命周期在父Worker生命周期范围内。 ### 推荐使用示例 @@ -428,7 +428,7 @@ workerPort.onmessage = (e: MessageEvents) => { ### 不推荐使用示例 -不建议在父Worker销毁后,子Worker仍向父Worker发送消息。 +不建议在父Worker销毁后,子Worker继续向父Worker发送消息。 ```ts // main thread @@ -499,7 +499,7 @@ workerPort.onmessage = (e: MessageEvents) => { } ``` -不建议在父Worker发起销毁操作的执行阶段创建子Worker。在创建子Worker线程之前,需确保父Worker线程始终处于存活状态,不建议在不确定父Worker是否发起销毁操作的情况下创建子Worker。 +不建议在父 Worker 发起销毁操作的执行阶段创建子 Worker。在创建子 Worker 之前,必须确保父 Worker 始终处于存活状态。不建议在不确定父 Worker 是否已经发起销毁操作的情况下创建子 Worker。 ```ts // main thread diff --git a/zh-cn/application-dev/arkts-utils/worker-invoke-mainthread-interface.md b/zh-cn/application-dev/arkts-utils/worker-invoke-mainthread-interface.md index ed7c228a69a..de787d9f42c 100644 --- a/zh-cn/application-dev/arkts-utils/worker-invoke-mainthread-interface.md +++ b/zh-cn/application-dev/arkts-utils/worker-invoke-mainthread-interface.md @@ -1,10 +1,10 @@ # Worker同步调用宿主线程的接口 -如果一个接口已在宿主线程中实现,Worker可以通过以下方式调用该接口。 +如果接口已在宿主线程中实现,Worker可按以下方式调用该接口。 -以下示例展示了Worker如何同步调用宿主线程的接口。 +以下示例展示了Worker同步调用宿主线程接口的方法。 -1. 首先,在宿主线程实现需要调用的接口,并创建Worker对象,在Worker对象上注册需要调用的对象。 +1. 在宿主线程实现接口调用,并创建Worker对象。接着,在Worker对象上注册调用对象。 ```ts // IconItemSource.ets @@ -52,7 +52,7 @@ workerInstance.postMessage("run setUp in picData"); ``` -2. 然后,在Worker中通过callGlobalCallObjectMethod接口可以调用宿主线程中的setUp()方法。 +2. 在Worker中调用宿主线程的setUp()方法,使用callGlobalCallObjectMethod接口。 ```ts // Worker.ets diff --git a/zh-cn/application-dev/arkts-utils/worker-postMessage-sendable.md b/zh-cn/application-dev/arkts-utils/worker-postMessage-sendable.md index 217d262e527..2d490aaf5c5 100644 --- a/zh-cn/application-dev/arkts-utils/worker-postMessage-sendable.md +++ b/zh-cn/application-dev/arkts-utils/worker-postMessage-sendable.md @@ -1,10 +1,10 @@ # 多级Worker间高性能消息通信 -多级[Worker](worker-introduction.md)(即通过父Worker创建子Worker的机制形成层级线程关系)间通信是一种常见的需求,由于Worker线程生命周期由用户自行管理,因此需要注意多级Worker生命周期的正确管理,建议开发者确保销毁父Worker前先销毁所有子Worker。 +多级[Worker](worker-introduction.md)(即通过父Worker创建子Worker的机制形成层级线程关系)间通信是常见需求。由于Worker线程生命周期由开发者管理,需确保销毁父Worker前先销毁所有子Worker。 -本文介绍如何在多级Worker间实现高性能消息通信,高性能消息通信的关键在于[Sendable对象](arkts-sendable.md),结合Worker的[postMessageWithSharedSendable接口](../reference/apis-arkts/js-apis-worker.md#postmessagewithsharedsendable12),可以实现线程间高性能的对象传递。以数据克隆场景为例,假设有三个Worker,一个父Worker和两个子Worker,父Worker负责创建子Worker,并向子Worker发送数据克隆任务,子Worker负责接收任务并执行数据克隆操作,完成后将克隆结果返回给父Worker。 +本文介绍如何在多级Worker间实现高性能消息通信。关键在于使用[Sendable对象](arkts-sendable.md),结合Worker的[postMessageWithSharedSendable接口](../reference/apis-arkts/js-apis-worker.md#postmessagewithsharedsendable12),可以实现线程间高性能的对象传递。以数据克隆场景为例,假设有一个父Worker和两个子Worker。父Worker负责创建子Worker,并向子Worker发送数据克隆任务。子Worker接收任务并执行数据克隆操作,完成后将克隆结果返回给父Worker。 -1. 准备一个Sendable类CopyEntry,用于封装克隆任务数据。 +1. 准备Sendable类CopyEntry,用于封装克隆任务数据。 ```ts // CopyEntry.ets @@ -21,7 +21,7 @@ } ``` -2. 准备两个Worker文件,父Worker文件为`ParentWorker.ets`,子Worker文件为`ChildWorker.ets`。父Worker负责分发克隆任务并判断任务全部完成后关闭子Worker与父Worker;子Worker负责接收任务并执行数据克隆操作,并在任务完成后通知父Worker。 +2. 准备两个Worker文件,父Worker文件为`ParentWorker.ets`,子Worker文件为`ChildWorker.ets`。父Worker分发克隆任务并判断任务全部完成后关闭子Worker和父Worker;子Worker接收任务并执行数据克隆操作,在任务完成后通知父Worker。 ```ts // ParentWorker.ets @@ -64,13 +64,13 @@ await asyncLock.lockAsync(() => { count1--; if (count1 == 0) { - // 如果copyWorker1的任务全部完成,则关闭copyWorker1 + // 关闭copyWorker1 console.info('copyWorker1 close'); copyWorker1.terminate(); } sum--; if (sum == 0) { - // 如果所有任务全部完成,则关闭父Worker + // 关闭父Worker workerPort.close(); } }) @@ -82,12 +82,12 @@ count2--; sum--; if (count2 == 0) { - // 如果copyWorker2的任务全部完成,则关闭copyWorker2 + // 关闭copyWorker2 console.info('copyWorker2 close') copyWorker2.terminate(); } if (sum == 0) { - // 如果所有任务全部完成,则关闭父Worker + // 关闭父Worker workerPort.close(); } }) @@ -124,7 +124,7 @@ } ``` -3. 在UI主进程页面,创建父Worker并准备克隆任务所需的数据,准备完成后将数据发送给父Worker。 +3. 在UI主进程页面,创建父Worker并准备克隆任务所需的数据,准备完成后发送给父Worker。 ```ts // Index.ets -- Gitee