我想知道这个关于未来的老问题的答案是否仍然适用于最近的语言构造async/await
。似乎是这样,因为下面的代码打印:
hello
good bye
hello
尽管导游说
futures:join宏允许在同时执行多个不同的futures时等待它们完成。
很明显,这是对许多其他异步系统(例如node.js(中预期行为的转移,与sleep
有关。
有什么根本原因吗?
use std::time::Duration;
use std::thread;
async fn sayHiOne() {
println!( " hello " );
thread::sleep( Duration::from_millis( 3000 ) );
println!( " good bye " );
} // ()
async fn sayHiTwo() {
println!( " hello " );
} // ()
async fn mainAsync() {
let fut1 = sayHiOne();
let fut2 = sayHiTwo();
futures::join!( fut1, fut2 );
} // ()
fn main() {
block_on( mainAsync() );
} // ()
添加:实际线程的预期行为(I(
fn main() {
let fut1 = do_async( move || {
println!( "hello" );
thread::sleep( Duration::from_millis( 3000 ) );
println!( "good bye" );
});
let fut2 = do_async( move || {
println!( "hello" );
});
fut1();
fut2();
}
use std::thread;
use std::time::Duration;
use std::sync::mpsc::channel;
fn do_async<TOut, TFun>( foo: TFun ) -> (impl FnOnce()-> TOut)
where
TOut: Send + Sync + 'static,
TFun: FnOnce() -> TOut + Send + Sync + 'static
{
let (sender, receiver)
= channel::< TOut >();
let hand = thread::spawn(move || {
sender.send( foo() ).unwrap();
} );
let f = move || -> TOut {
let res = receiver.recv().unwrap();
hand.join().unwrap();
return res;
};
return f;
} // ()
由于标准/原始thread::sleep
是阻塞的,因此异步库提供了用于睡眠的非阻塞版本async_std::task::sleep( ... )
。它将与.await
(无括号(一起使用:
task::sleep::( Duration::from_millis( 1 ) ).await;
该sleep
具有与不稳定版本相同的效果:yield_now,在某种意义上是
将当前正在执行的future移到执行队列的后面,为其他future的执行腾出空间。这在将来运行CPU密集型操作后尤其有用。
所以我想,预期用途是";亲切地"当任务计划执行长时间工作时,在未来的任务中共享线程的使用。
是的,它仍然适用。从根本上讲,它必须是这样的,因为正如链接的答案所说,每个异步函数都将在同一个线程上运行——std::thread::sleep
对异步一无所知,因此会使整个线程休眠。
Nodejs(以及一般的JavaScript(更多地是围绕异步设计的,因此语言原语和语言运行时在这种方式下更具异步意识。