鸿蒙多线程开发——线程间数据通信对象03(sendable)

1、简 介

在传统JS引擎上,对象的并发通信开销的优化方式只有一种,就是把实现下沉到Native侧,通过Transferable对象的转移或共享方式降低并发通信开销。而开发者仍然还有大量对象并发通信的诉求,这个问题在业界的JS引擎实现上并没有得到解决。

ArkTS提供了Sendable对象类型,在并发通信时支持通过引用传递来解决上述问题。

Sendable对象为可共享的,其跨线程前后指向同一个JS对象,如果其包含了JS或者Native内容,均可以直接共享,如果底层是Native实现的,则需要考虑线程安全性。通信过程如下图所示:

图片

与其它ArkTS对象不一样的是,符合Sendable协议的数据对象在运行时必须是类型固定的对象。

当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争。因此,ArkTS提供了异步锁的机制来避免不同并发实例间的数据竞争。同时,还可以通过对象冻结接口冻结对象,将其变为只读对象,就可以不用考虑数据的竞争问题。

Sendable对象提供了并发实例间高效的通信效率,即引用传递的能力,一般适用于开发者自定义大对象需要线程间通信的场景,例如子线程读取数据库的数据返回主线程。

2、Sendable对象类型基础概念

2.1、Sendable协议

Sendable协议定义了ArkTS的可共享对象体系及其规格约束。符合Sendable协议的数据(以下简称Sendable对象)可以在ArkTS并发实例间传递。

默认情况下,Sendable数据在ArkTS并发实例间(包括主线程、TaskPool、Worker线程)传递的行为是引用传递。同时,ArkTS也支持Sendable数据在ArkTS并发实例间拷贝传递。

2.2、ISendable接口

在ArkTS语言基础库@arkts.lang中引入了interface ISendable,没有任何必须的方法或属性。ISendable是所有Sendable类型(除了null和undefined)的父类型。ISendable主要用在开发者自定义Sendable数据结构的场景中。类装饰器@Sendable装饰器是implement ISendable的语法糖。

2.3、@Sendable装饰器

用于声明并校验Sendable类以及Sendable函数。有以下需要注意的使用限制:

  • 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。

    2. 禁止使用闭包变量。

    3. 不支持通过#定义私有属性,需用private。

    4. 不支持计算属性。

  • 成员属性必须显式初始化。成员属性不能跟感叹号。

  • 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量,定义在顶层的Sendable class和Sendable function除外。

  • 不支持增加属性、不支持删除属性、允许修改属性,修改前后属性的类型必须一致、不支持修改方法。

Sendable类使用示例如下:

@Sendableclass SendableTestClass {
  
    desc: string = "sendable: this is SendableTestClass ";  num: number = 5;  printName() {
  
      console.info("sendable: SendableTestClass desc is: " + this.desc);  }  get getNum(): number {
  
      return this.num;  }}

Sendable函数使用示例如下:

@Sendabletype SendableFuncType = () => void;@Sendableclass TopLevelSendableClass {
  
  
### 鸿蒙 OS 数据库 CRUD 工具类实现 #### 关系型数据库简介 在鸿蒙操作系统中,关系型数据库(Relational Database, RDB)用于管理和操作结构化数据。这种类型的数据库基于SQLite组件提供了全面的数据管理功能,包括但不限于增、删、改、查等基本操作,并允许执行自定义SQL语句以应对复杂需求[^1]。 #### 创建CRUD工具类 为了简化应用程序中的数据库交互逻辑,通常会设计一个专门负责这些任务的辅助类——即所谓的“工具类”。下面是一个简单的Java风格伪代码例子展示如何构建这样一个类: ```java public class DbHelper { private SQLiteDatabase db; public DbHelper(Context context) { // 初始化 SQLiteOpenHelper 或其他方式打开/创建数据库连接 this.db = new MyDatabaseHelper(context).getWritableDatabase(); } /// 插入新记录到指定表内 public long insert(String table, ContentValues values){ return db.insert(table,null,values); } /// 更新现有记录 public int update(String table,ContentValues values,String whereClause,Object[] whereArgs){ return db.update(table,values,whereClause,whereArgs); } /// 删除符合条件的记录 public int delete(String table ,String whereClause,Object[] whereArgs){ return db.delete(table,whereClause,whereArgs); } /// 查询特定条件下的多条记录并返回Cursor对象 public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit){ return db.query(table,columns,selection,selectionArgs,groupBy,having,orderBy,limit); } } ``` 此`DbHelper`类封装了常见的四种主要操作:插入(`insert`)、更新(`update`)、删除(`delete`)以及查询(`query`)。通过这种方式,开发者可以在应用的不同部分重复利用这段代码而无需每次都编写相同的SQL命令。 对于更高级的功能,比如事务处理或多线程环境下的并发访问控制,则可能需要进一步扩展此类的设计模式或引入额外的支持框架和服务。 #### 获取 Sendable 数据 当涉及到跨线程通信时,可以通过调用 `ResultSet.getSendableRow()` 方法来获得可序列化的行数据实例,从而安全地将其传递给另一个线程进行后续处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值