Skip to content

@Async 异步执行

@Async 是 ACE Framework 提供的异步执行切面宏。标注在 @Service 的方法上后,框架会在独立子协程中执行该方法,调用方立即获得一个 Future<T> 句柄,可按需等待结果或继续执行其他逻辑。

快速上手

cangjie
package demo.service

import ace.framework.*

@Service
class ExternalClient {

    // 调用外部 API A,在子协程中执行
    @Async
    func fetchFromServiceA(id: Int64): String {
        // 模拟 I/O 耗时
        Thread.sleep(Duration.millisecond * 200)
        return "result-A-${id}"
    }

    // 调用外部 API B,在子协程中执行
    @Async
    func fetchFromServiceB(id: Int64): String {
        Thread.sleep(Duration.millisecond * 150)
        return "result-B-${id}"
    }
}

@Async 方法的实际返回类型在宏展开后变为 Future<T>(原返回类型 T 被包裹),调用方无需手动创建协程。

并行调用示例

cangjie
package demo.controller

import ace.framework.*

@Controller["/api"]
class AggregateController {
    @Inject
    var client!: ExternalClient

    @Get["/aggregate/:id"]
    func aggregate(@PathParam id: Int64): String {
        // 两个子协程并行发起,不互相阻塞
        let futureA = client.fetchFromServiceA(id)
        let futureB = client.fetchFromServiceB(id)

        // 等待两个结果(总耗时 ≈ max(200, 150) = 200 ms,而非 350 ms)
        let a = futureA.get()
        let b = futureB.get()

        return "${a} | ${b}"
    }
}

API 说明

成员类型说明
future.get()T阻塞直到协程完成,返回结果;若抛出异常则重新抛出
future.tryGet()Option<T>非阻塞轮询,未完成返回 None,已完成返回 Some(value)
future.getOrDefault(default)T阻塞等待,若抛异常则返回 default
future.isCompleted()Bool查询协程是否已结束

tryGet 轮询示例

cangjie
let future = client.fetchFromServiceA(42)

// 主协程做其他工作,偶尔检查
var result: Option<String> = None
while (result.isNone()) {
    doOtherWork()
    result = future.tryGet()
}
println(result.getOrThrow())

注意事项

不能与 @Transactional 混用

@Async 会在新协程中执行,而事务上下文绑定在原协程上。若方法同时标注 @Transactional,子协程内的数据库操作将在事务上下文之外执行,导致数据不一致。正确做法:在调用 @Async 方法之前完成事务操作,或将事务与异步逻辑分拆到不同方法。

适用场景

  • 并行调用多个外部 HTTP/RPC 服务
  • 异步发送邮件、消息推送等"发完不管"任务
  • 预热缓存、异步写日志等副作用操作

异常不会自动传播

子协程抛出的异常不会自动打印,只有在调用 future.get() 时才会重新抛出。"发完不管"模式下,请在方法内部 try/catch 并记录日志,否则异常将被静默丢弃。

与普通协程对比

方式代码侵入返回值适用场景
@Async无(只加注解)Future<T>Service 方法并行化
手动 spawn { }有(改动调用方)Future<T>细粒度控制协程生命周期
Thread.sleep + 手动同步自行管理底层特殊需求

基于 Apache-2.0 许可证发布