鸿蒙中 线程通信-Sendable对象

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、Sendable 对象

1. 背景

  • 传统问题:JS引擎中对象并发通信开销大,需通过Native侧Transferable对象优化。

  • ArkTS解决方案:提供Sendable对象类型,支持并发通信时通过引用传递降低开销。

  • 核心特性:Sendable对象可跨线程共享,指向同一个JS对象,避免拷贝开销。

2. 通信机制

  • 引用传递:默认采用引用传递方式跨线程共享。

  • 线程安全:如包含Native实现,需确保线程安全性。

  • 数据竞争防护:提供异步锁、异步等待、对象冻结等机制防止数据竞争。

二、Sendable 结构

1. Sendable协议

  • 定义了ArkTS可共享对象体系及其规格约束。

  • 符合协议的数据可在ArkTS并发实例间传递。

2. ISendable接口

  • 位于@arkts.lang基础库中,无方法或属性。

  • 是所有Sendable类型(除null和undefined)的父类型。

  • @Sendable装饰器implement ISendable的语法糖。

3. Sendable类型分类

  • Sendable class:使用@Sendable装饰器标注的类。

  • Sendable function:使用@Sendable装饰器标注的函数。

  • Sendable interface:继承ISendable的接口。

三、Sendable 支持的数据类型

1. 基础类型

  • boolean、number、string、bigint、null、undefined

  • const enum(常量枚举)

2. 标准库类型

  • 容器类型:需显式引入@arkts.collections

  • 异步锁对象:需显式引入@arkts.utils

  • 异步等待对象:需显式引入@arkts.utils

  • SendableLruCache对象:需显式引入@arkts.utils

3. 系统对象

  • 共享用户首选项

  • 基于Sendable对象的图片处理、资源管理

  • SendableContext对象管理

4. 其他类型

  • 元素均为Sendable类型的union type数据

  • 自定义的Native Sendable对象

  • 标注了@Sendable装饰器的class和function

5. 不支持的类型

  • JS内置对象:遵循结构化克隆算法,拷贝传递

  • 对象字面量和数组字面量:拷贝传递,非Sendable类型

四、Sendable 实现原理

1. 内存模型

  • 共享堆(SharedHeap):进程级别堆空间,所有线程可访问

  • 本地堆(LocalHeap):单个并发实例访问,线程隔离

  • Sendable对象分配在SharedHeap中,实现跨线程内存共享

2. 生命周期管理

  • Sendable对象存活取决于所有并发实例是否存在对其的引用

  • SharedHeap不能引用LocalHeap中的对象

五、@Sendable 装饰器

1. 基本规范

项目规范说明
装饰器参数
使用场景仅Stage模型的.ets文件
函数类型普通function、Async function
类继承Sendable class只能继承Sendable class

2. 属性类型限制

  • 支持:string、number、boolean、bigint、null、undefined、Sendable class、collections容器集、异步锁、SendableLruCache等

  • 禁止:使用闭包变量(顶层定义除外)

  • 不支持:通过#定义私有属性(需用private)、计算属性

3. 其他限制

  • 成员属性必须显式初始化,不能使用感叹号

  • 不支持增加或删除属性,允许修改属性(类型必须一致)

  • 不支持修改方法

  • 从API 18开始支持访问本文件导出的变量

4. 适用场景

  • 在TaskPool或Worker中使用类方法或Sendable函数

  • 传输大数据量对象:传输100KB数据效率提升约20倍,1MB数据提升约100倍

六、使用示例

1. Sendable 类

@Sendable
class DataModel {
    status: ModelStatus = ModelStatus.ACTIVE;
    data: string = "initial data";
    
    updateStatus(newStatus: ModelStatus): void {
        this.status = newStatus;
    }
    
    displayInfo(): void {
        console.info(`Model status: ${this.status}, data: ${this.data}`);
    }
}

@Concurrent
function processModel(model: DataModel): void {
    model.updateStatus(ModelStatus.PROCESSING);
    model.displayInfo();
}

2. Sendable 方法

// 定义Sendable函数类型
@Sendable
type DataProcessor = (input: string) => string;

@Sendable
class ProcessingService {
    processor: DataProcessor;
    
    constructor(processor: DataProcessor) {
        this.processor = processor;
    }
    
    executeProcessing(input: string): string {
        return this.processor(input);
    }
}

@Sendable
function textTransform(input: string): string {
    return input.toUpperCase() + "_PROCESSED";
}

// 使用示例
const service = new ProcessingService(textTransform);
const result = service.executeProcessing("hello world");
console.info(`Processing result: ${result}`);

七、优势

  • 大幅提升传输效率

  • 避免了序列化/反序列化的性能开销

  • 特别适合大对象跨线程通信场景

八、线程安全方面

  • 使用异步锁(AsyncLock)避免数据竞争

  • 使用异步等待(ConditionVariable)控制多线程时序

  • 通过对象冻结接口将对象设为只读,避免并发修改

### 鸿蒙系统中 Sendable 接口或类的使用方法 鸿蒙系统中的 `Sendable` 是一种用于跨线程、跨进程通信的设计规范,它确保对象能够在不同的上下文中安全地传递。以下是关于 `Sendable` 的详细说明和示例代码。 #### 1. Sendable 的基本概念 `Sendable` 是一种标记性装饰器,用于定义可以在分布式任务调度或线程间传递的对象。为了满足 `Sendable` 的要求,类或接口需要遵循特定的规则[^2]。例如,成员变量不能直接使用普通数组,而必须使用 `collections.Array` 等支持的类型。 #### 2. Sendable 类的约束条件 在设计 `Sendable` 类时,必须遵守以下规则: - 成员变量不能包含不支持的类型(如普通数组)。 - 不允许对成员变量使用 `!` 断言操作符[^2]。 - 必须确保所有成员变量是可序列化的或符合 `Sendable` 规范[^3]。 #### 3. 示例代码 以下是一个符合 `Sendable` 规范的类定义及使用示例: ```typescript // 正确的 Sendable 类定义 class A { state: number = 0; } @Sendable class SendableA { state: number = 0; } // 实例化并转换为 Sendable 对象 let a1: A = new SendableA() as A; console.log(a1.state); // 输出:0 ``` 上述代码展示了如何正确地将一个 `Sendable` 类实例转换为普通类实例。需要注意的是,`Sendable` 类的成员变量必须是简单类型或支持的复杂类型[^3]。 #### 4. 错误案例分析 以下是一个违反 `Sendable` 规范的示例: ```typescript class A { state: number = 0; } @Sendable class SendableA { state: number = 0; } // 错误的类型转换 let a2: SendableA = new A() as SendableA; // ❌ 错误:A 不是 Sendable 类型 ``` 此代码尝试将非 `Sendable` 类型的实例强制转换为 `Sendable` 类型,这会导致运行时错误[^1]。 #### 5. 使用 Sendable 的注意事项 - 确保所有成员变量符合 `Sendable` 的约束条件[^2]。 - 避免在 `Sendable` 类中使用不支持的数据结构或操作符[^3]。 - 在跨线程或跨进程传递对象时,优先使用 `Sendable` 类型以保证安全性[^1]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值