pub struct Runtime { /* 私有字段 */ }展开描述
Tokio 运行时。
运行时提供了运行异步任务所需的 I/O 驱动、任务调度器、计时器 以及阻塞线程池。
Runtime 实例可以使用 new 或 Builder 创建。不过,大多数用户会在入口点使用 #[tokio::main] 属性注解。
有关更多详细信息,请参阅 模块级 文档。
§Shutdown
关闭运行时是通过 drop 该值或调用 shutdown_background 或 shutdown_timeout 来完成的。
通过 Runtime::spawn 生成的任务会一直运行,直到它们让步。然后它们会被 drop。它们不保证会运行到完成,但如果它们在完成之前不让步,则可能会运行到完成。
通过 Runtime::spawn_blocking 生成的阻塞函数会一直运行,直到它们返回。
发起关闭的线程会一直阻塞,直到所有生成的工作都已停止。这可能需要无限长的时间。Drop 实现会永远等待这一过程。
如果不想永远等待,可以使用 shutdown_background 和 shutdown_timeout 方法。当达到超时时,未及时停止的已生成工作以及运行它们的线程会被泄漏。工作会继续运行,直到满足停止条件之一,但发起关闭的线程将不再阻塞。
一旦运行时被 drop,绑定到它的所有未完成的 I/O 资源将不再可用。对它们调用任何方法都将导致错误。
§Sharing
有几种方法可以建立对 Tokio 运行时的共享访问:
使用 Arc<Runtime> 或 Handle 允许你对运行时执行各种操作,例如生成新任务或进入运行时上下文。这两种类型都可以克隆,以创建一个允许访问同一运行时的新句柄。通过将克隆传递到不同的任务或线程,你将能够从这些任务或线程访问运行时。
Arc<Runtime> 与 Handle 之间的区别在于,Arc<Runtime> 会阻止运行时关闭,而 Handle 则不会阻止。这是因为运行时的关闭发生在 Runtime 对象的析构函数运行时。
对 shutdown_background 和 shutdown_timeout 的调用需要 Runtime 类型的独占所有权。在使用 Arc<Runtime> 时,当只剩下一个强引用计数时,可以通过 Arc::try_unwrap 来实现这一点。
运行时上下文是通过 Runtime::enter 或 Handle::enter 方法进入的,这些方法使用线程局部变量来存储当前运行时。只要你在运行时上下文中,像 tokio::spawn 这样的方法将使用你所在上下文中的运行时。
实现§
源代码§impl Runtime
impl Runtime
源代码pub fn handle(&self) -> &Handle
pub fn handle(&self) -> &Handle
返回运行时 spawner 的句柄。
返回的句柄可用于派生在此运行时上运行的任务,并且可以克隆以便将 Handle 移到其他线程。
在 current_thread 运行时的句柄上调用 Handle::block_on 容易出错。有关更多信息,请参阅 Handle::block_on 的文档。
§示例
use tokio::runtime::Runtime;
let rt = Runtime::new()
.unwrap();
let handle = rt.handle();
// Use the handle...源代码pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output> ⓘ
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output> ⓘ
将 future 派生到 Tokio 运行时。
这会将给定的 future 派生到运行时的执行器上,通常是线程池。然后由该线程池负责轮询该 future 直到其完成。
当调用 spawn 时,提供的 future 将立即开始在后台运行,即使你未 await 返回的 JoinHandle 也是如此(假设运行时正在运行)。
有关更多详细信息,请参阅 模块级 文档。
§示例
use tokio::runtime::Runtime;
// 创建运行时
let rt = Runtime::new().unwrap();
// Spawn a future onto the runtime
rt.spawn(async {
println!("now running on a worker thread");
});源代码pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R> ⓘ
pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R> ⓘ
在专用于阻塞操作的执行器上运行所提供的函数。
§示例
use tokio::runtime::Runtime;
// 创建运行时
let rt = Runtime::new().unwrap();
// Spawn a blocking function onto the runtime
rt.spawn_blocking(|| {
println!("now running on a worker thread");
});源代码pub fn block_on<F: Future>(&self, future: F) -> F::Output
pub fn block_on<F: Future>(&self, future: F) -> F::Output
在 Tokio 运行时上运行 future 直到完成。这是运行时的入口点。
这会在当前线程上运行给定的 future,阻塞直到它完成,并产生其解析结果。future 内部生成的任何任务或计时器都将在运行时上执行。
§Non-worker future
请注意,此函数所需的 future 不会作为 worker 运行。期望此处的 future 生成其他任务。在此提供的 future 上等待其他 future 的性能不会像作为 worker 生成的那些一样快。
§Multi thread scheduler
当使用多线程调度器时,这将允许 future 在整体运行时的 io 驱动和计时器上下文中运行。
任何已生成的任务将在 block_on 返回后继续运行。
§Current thread scheduler
当启用当前线程调度器时,可以从多个线程并发调用 block_on。第一次调用将取得 io 和计时器驱动的所有权。这意味着不拥有驱动的其他线程将挂接到该驱动。当第一个 block_on 完成时,其他线程将能够“窃取”该驱动以允许继续执行其 future。
任何已生成的任务将在 block_on 返回后被挂起。再次调用 block_on 将恢复先前生成的任务。
§恐慌
如果提供的 future 发生 panic,或者在异步执行上下文中调用,则此函数会发生 panic。
§示例
use tokio::runtime::Runtime;
// 创建运行时
let rt = Runtime::new().unwrap();
// 执行 future,阻塞当前线程直到完成
rt.block_on(async {
println!("hello");
});源代码pub fn enter(&self) -> EnterGuard<'_>
pub fn enter(&self) -> EnterGuard<'_>
进入运行时上下文。
这允许你构造在创建时必须有执行器可用的类型,例如 Sleep 或 TcpStream。它还允许你调用诸如 tokio::spawn 之类的方法。
§示例
use tokio::runtime::Runtime;
use tokio::task::JoinHandle;
fn function_that_spawns(msg: String) -> JoinHandle<()> {
// Had we not used `rt.enter` below, this would panic.
tokio::spawn(async move {
println!("{}", msg);
})
}
fn main() {
let rt = Runtime::new().unwrap();
let s = "Hello World!".to_string();
// By entering the context, we tie `tokio::spawn` to this executor.
let _guard = rt.enter();
let handle = function_that_spawns(s);
// Wait for the task before we end the test.
rt.block_on(handle).unwrap();
}源代码pub fn shutdown_timeout(self, duration: Duration)
pub fn shutdown_timeout(self, duration: Duration)
关闭运行时,并最多等待 duration 时间让所有已派生的工作停止。
有关更多详细信息,请参阅 结构体级文档。
§示例
use tokio::runtime::Runtime;
use tokio::task;
use std::thread;
use std::time::Duration;
fn main() {
let runtime = Runtime::new().unwrap();
runtime.block_on(async move {
task::spawn_blocking(move || {
thread::sleep(Duration::from_secs(10_000));
});
});
runtime.shutdown_timeout(Duration::from_millis(100));
}源代码pub fn shutdown_background(self)
pub fn shutdown_background(self)
关闭运行时,但不等待任何已派生的工作停止。
如果你想从另一个运行时中 drop 一个运行时,这会很有用。通常情况下,drop 一个运行时会无限期阻塞以等待已派生的阻塞任务完成,而异步上下文通常不允许这样做。通过调用 shutdown_background(),你可以从此类上下文中 drop 该运行时。
但请注意,因为我们不等待任何阻塞任务完成,这可能会导致资源泄漏(即任何阻塞任务仍在运行,直到它们返回。
有关更多详细信息,请参阅 结构体级文档。
此函数等价于调用 shutdown_timeout(Duration::from_nanos(0))。
use tokio::runtime::Runtime;
fn main() {
let runtime = Runtime::new().unwrap();
runtime.block_on(async move {
let inner_runtime = Runtime::new().unwrap();
// ...
inner_runtime.shutdown_background();
});
}源代码pub fn metrics(&self) -> RuntimeMetrics
pub fn metrics(&self) -> RuntimeMetrics
返回一个视图,可用于获取运行时性能的相关信息。