rust
#[derive(Debug,Copy,Clone)]
struct P{}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let s = P{};
let sleep_futures:Vec<_> = (1..=10).map(move |t|{
tokio::task::spawn_blocking(move||{println!("s:{:?}",s);})
}).collect();
for k in sleep_futures{
k.await;
}
}
这段代码因为是tokio::task::spawn_blocking开启了多线程,多线程内部对s必须就是有所有权。那么这里tokio::task::spawn_blocking(move||{println!("s:{:?}",s);})有move还是不够的,因为这里是多个线程都有对s的所有权,所以这里必须P是copy和Clone都存在。然后这里move的时候,默认是走的Copy的trait。
这里不加Clone和Copy的trait不行,但是如果自己实现Clone。又不会进入到方法内部,不了解原因。
rust
#[derive(Debug,Copy)]
struct P{}
impl Clone for P{
fn clone(&self) -> Self {
println!("hello");
P{}
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let s = P{};
let sleep_futures:Vec<_> = (1..=10).map(move |t|{
tokio::task::spawn_blocking(move||{println!("s:{:?}",s);})
}).collect();
for k in sleep_futures{
let _= k.await;
}
}
但是这里面不会打印hello。
Copy
trait 表示一种类型的值可以通过按位复制来进行拷贝,而不是通过移动。对于实现了 Copy
的类型,clone
方法通常不会被调用,因为拷贝操作是通过简单的位复制来完成的。
而且如果是使用一次s。则rust的编译器知道只使用一次。这种情况下,P不用实现Copy
rust
#[derive(Debug)]
struct P{
I:i32
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let s = P{I:0};
let k = tokio::task::spawn_blocking(move||{println!("s:{:?}",s);});
let _= k.await;
}
但是如果是单线程内部,那可以不用实现copy
rust
#[derive(Debug)]
struct P{
I:i32
}
fn main() {
let s = P{I:0};
let sleep_futures:Vec<_> = (1..=10).map(move |t|{
println!("s:{:?}",s);
}).collect();
}
可以看出rust的编译器非常智能
包括以下这种,不需要实现copy
rust
use futures::future::join_all;
use std::time::Instant;
async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) {
std::thread::sleep(std::time::Duration::from_millis(duration_ms));
println!(
"future {id} slept for {duration_ms}ms, finished after {}ms",
start.elapsed().as_millis()
);
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let start = Instant::now();
let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10));
join_all(sleep_futures).await;
}
async fn sleep_ms(start: P, id: u64, duration_ms: u64) {
std::thread::sleep(std::time::Duration::from_millis(duration_ms));
println!(
"future,{:?} {id} slept for {duration_ms}ms, finished after {:?}ms",
std::thread::current().id(),start
);
}
#[derive(Debug)]
struct P{
I:i32
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let start = P{ I: 0 };
let sleep_futures = (1..=10).map( |t| sleep_ms(start, t, t * 10));
join_all(sleep_futures).await;
}
报错,原因是:
但是:
rust
#[derive(Debug)]
struct P{
I: i32,
}
fn main() {
let mut s = P { I: 0 };
let sleep_futures: Vec<_> = (1..=10).map(move |t| {
s.I = 100;
println!("s:{:?}", s); // s 被移动到闭包内部并被使用
}).collect();
}
使用了move依然不会报错。原因是:
这样就报错了
rust
#[derive(Debug)]
struct P{
I:i32
}
fn main() {
let mut s = P { I: 0 };
let mut i = 0;
while i < 3 {
i += 1;
let sleep_futures: Vec<_> = (1..=10).map( move|t| {
s.I =100;
println!("s:{:?}", s);
}).collect();
}
}
而
rust
#[derive(Debug)]
struct P{
I:i32
}
fn main() {
let mut s = P { I: 0 };
let mut i = 0;
while i < 3 {
i += 1;
let sleep_futures: Vec<_> = (1..=10).map( |t| {
s.I =100;
println!("s:{:?}", s);
}).collect();
}
}
可以保证不错。看来确实这里的s是当作&mut进行编译的,而不是值的所有权转移