You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby Async Gem基础用法示例与顶层调用阻塞问题解答

async gem 核心运行逻辑与基础用法规范

两段代码的行为差异原因

第一个示例无法实现并行的核心原因是:每次在顶层调用Async时,都会独立创建并运行reactor,且会阻塞到当前reactor的任务执行完成后才会进入下一次循环,本质是10个串行的独立任务,总耗时接近10*1.6s。

顶层与嵌套Async调用的行为差异

Async调用的执行逻辑完全取决于当前上下文是否存在运行中的reactor:

  1. 无已运行reactor(多为顶层调用场景):Async会先创建reactor,把传入的代码块作为根任务运行,阻塞当前线程直到reactor内所有任务执行完毕
  2. 已有运行中reactor(嵌套在其他Async代码块内的场景):Async只会把传入的代码块作为子任务提交给当前reactor调度,不会阻塞当前执行流,子任务会和其他同级别子任务并行调度。

标准基础用法规范

1. 单个顶层Async块作为异步入口

所有异步任务都需要嵌套在同一个顶层Async块内部,避免重复创建独立reactor导致串行执行:

require 'async'
require 'httparty'

# 单个顶层Async块作为异步程序唯一入口
Async do
  # 内部所有Async调用都是非阻塞的子任务,由同一个reactor统一调度
  10.times do |i|
    Async do
      resp = HTTParty.get("https://httpbin.org/delay/1.6")
      puts "任务#{i}执行完成,状态码:#{resp.code}"
    end
  end
end
# 顶层Async块外的代码会等待所有异步任务完成后才执行
puts "所有任务执行完毕"

2. 显式等待子任务(可选)

如果需要获取子任务的返回值、或者控制子任务的执行顺序,可以调用任务对象的#wait方法:

Async do
  # 保存子任务对象
  task = Async do
    HTTParty.get("https://httpbin.org/delay/1.6")
  end
  # 等待子任务完成并获取返回值
  resp = task.wait
  puts "请求结果:#{resp.body}"
end

3. IO操作无需额外改造

Ruby 3.0+内置的Fiber调度机制会自动拦截标准库的阻塞IO操作(HTTP请求、文件读写、数据库查询等),原有IO代码不需要修改即可实现异步调度。

内容的提问来源于stack exchange,提问作者Christopher Oezbek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 10:27:04